summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Berthold Stoeger <bstoeger@mail.tuwien.ac.at>2018-10-15 21:17:23 +0200
committerGravatar Dirk Hohndel <dirk@hohndel.org>2018-10-15 20:55:03 -0400
commit813c5705242de74e7770e79c8d50a2041c486e35 (patch)
tree9063d3a6e2301a5efad396bc178a36b4ba5b9bea
parent36043e8af22f7e789d6231c18ed6429f5236d889 (diff)
downloadsubsurface-813c5705242de74e7770e79c8d50a2041c486e35.tar.gz
Core: copy whole list in copy_dc_renumber()
copy_dc_renumber() is an internal function to copy dive computers and renumber the cylinders. Since only the structure was copied, in the case of multi-dc dives, the merged dives shared the same computer. If one of them was freed, use-after-free crashes would happen. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
-rw-r--r--core/dive.c22
1 files changed, 16 insertions, 6 deletions
diff --git a/core/dive.c b/core/dive.c
index 0226cc2c1..c1cc2e11a 100644
--- a/core/dive.c
+++ b/core/dive.c
@@ -489,14 +489,24 @@ static void copy_dc(const struct divecomputer *sdc, struct divecomputer *ddc)
static void dc_cylinder_renumber(struct dive *dive, struct divecomputer *dc, const int mapping[]);
-/* copy dive computer and renumber the cylinders */
+/* copy dive computer list and renumber the cylinders
+ * space for the first divecomputer is provided by the
+ * caller, the remainder is allocated */
static void copy_dc_renumber(struct dive *d, const struct divecomputer *sdc, struct divecomputer *ddc, const int cylinders_map[])
{
- *ddc = *sdc;
- ddc->model = copy_string(sdc->model);
- copy_samples(sdc, ddc);
- copy_events(sdc, ddc);
- dc_cylinder_renumber(d, ddc, cylinders_map);
+ for (;;) {
+ *ddc = *sdc;
+ ddc->model = copy_string(sdc->model);
+ copy_samples(sdc, ddc);
+ copy_events(sdc, ddc);
+ dc_cylinder_renumber(d, ddc, cylinders_map);
+ if (!sdc->next)
+ break;
+ sdc = sdc->next;
+ ddc->next = calloc(1, sizeof(struct divecomputer));
+ ddc = ddc->next;
+ }
+ ddc->next = NULL;
}
/* copy an element in a list of pictures */