fix double-frees in error path when resolving deltas fails
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
diff --git a/lib/pack.c b/lib/pack.c
index 9bf9884..9de81b2 100644
--- a/lib/pack.c
+++ b/lib/pack.c
@@ -740,25 +740,19 @@ resolve_offset_delta(struct got_delta_chain *deltas,
err = add_delta(deltas, delta_offset, tslen, delta_type, delta_size,
delta_data_offset, delta_buf, delta_len);
if (err)
- goto done;
+ return err;
/* An offset delta must be in the same packfile. */
- if (base_offset >= pack->filesize) {
- err = got_error(GOT_ERR_PACK_OFFSET);
- goto done;
- }
+ if (base_offset >= pack->filesize)
+ return got_error(GOT_ERR_PACK_OFFSET);
err = parse_object_type_and_size(&base_type, &base_size, &base_tslen,
pack, base_offset);
if (err)
- goto done;
+ return err;
- err = resolve_delta_chain(deltas, packidx, pack, base_offset,
+ return resolve_delta_chain(deltas, packidx, pack, base_offset,
base_tslen, base_type, base_size, recursion - 1);
-done:
- if (err)
- free(delta_buf);
- return err;
}
static const struct got_error *
@@ -774,7 +768,7 @@ resolve_ref_delta(struct got_delta_chain *deltas, struct got_packidx *packidx,
uint64_t base_size;
size_t base_tslen;
off_t delta_data_offset;
- uint8_t *delta_buf = NULL;
+ uint8_t *delta_buf;
size_t delta_len;
if (delta_offset >= pack->filesize)
@@ -796,7 +790,7 @@ resolve_ref_delta(struct got_delta_chain *deltas, struct got_packidx *packidx,
err = got_inflate_to_mem_mmap(&delta_buf, &delta_len, pack->map,
mapoff, pack->filesize - mapoff);
if (err)
- goto done;
+ return err;
} else {
ssize_t n = read(pack->fd, &id, sizeof(id));
if (n < 0)
@@ -805,43 +799,33 @@ resolve_ref_delta(struct got_delta_chain *deltas, struct got_packidx *packidx,
return got_error(GOT_ERR_BAD_PACKFILE);
err = got_inflate_to_mem_fd(&delta_buf, &delta_len, pack->fd);
if (err)
- goto done;
+ return err;
}
err = add_delta(deltas, delta_offset, tslen, delta_type, delta_size,
delta_data_offset, delta_buf, delta_len);
if (err)
- goto done;
+ return err;
/* Delta base must be in the same pack file. */
idx = got_packidx_get_object_idx(packidx, &id);
- if (idx == -1) {
- err = got_error(GOT_ERR_BAD_PACKFILE);
- goto done;
- }
+ if (idx == -1)
+ return got_error(GOT_ERR_BAD_PACKFILE);
base_offset = get_object_offset(packidx, idx);
- if (base_offset == (uint64_t)-1) {
- err = got_error(GOT_ERR_BAD_PACKIDX);
- goto done;
- }
+ if (base_offset == (uint64_t)-1)
+ return got_error(GOT_ERR_BAD_PACKIDX);
- if (base_offset >= pack->filesize) {
- err = got_error(GOT_ERR_PACK_OFFSET);
- goto done;
- }
+ if (base_offset >= pack->filesize)
+ return got_error(GOT_ERR_PACK_OFFSET);
err = parse_object_type_and_size(&base_type, &base_size, &base_tslen,
pack, base_offset);
if (err)
- goto done;
+ return err;
- err = resolve_delta_chain(deltas, packidx, pack, base_offset,
+ return resolve_delta_chain(deltas, packidx, pack, base_offset,
base_tslen, base_type, base_size, recursion - 1);
-done:
- if (err)
- free(delta_buf);
- return err;
}
static const struct got_error *
@@ -896,6 +880,9 @@ open_delta_object(struct got_object **obj, struct got_packidx *packidx,
memcpy(&(*obj)->id, id, sizeof((*obj)->id));
(*obj)->pack_offset = offset + tslen;
+ SIMPLEQ_INIT(&(*obj)->deltas.entries);
+ (*obj)->flags |= GOT_OBJ_FLAG_DELTIFIED;
+
(*obj)->path_packfile = strdup(pack->path_packfile);
if ((*obj)->path_packfile == NULL) {
err = got_error_from_errno("strdup");
@@ -904,9 +891,6 @@ open_delta_object(struct got_object **obj, struct got_packidx *packidx,
(*obj)->flags |= GOT_OBJ_FLAG_PACKED;
(*obj)->pack_idx = idx;
- SIMPLEQ_INIT(&(*obj)->deltas.entries);
- (*obj)->flags |= GOT_OBJ_FLAG_DELTIFIED;
-
err = resolve_delta_chain(&(*obj)->deltas, packidx, pack, offset,
tslen, delta_type, delta_size, GOT_DELTA_CHAIN_RECURSION_MAX);
if (err)