commit f18c433aae68e5537cf67eae05c0343e970307ad from: Stefan Sperling date: Tue May 31 08:44:55 2022 UTC avoid get_delta_chain_max_size() in dump_delta_chain_to_mem() commit - 6395114c60289f3ac0f28c0fc4b5dfcef8690cdf commit + f18c433aae68e5537cf67eae05c0343e970307ad blob - 280287ef843efeb4547446a984e2d924c66f9374 blob + 2c612a33c5d96977b8bbe4ac08c2fc41cc78381b --- lib/pack.c +++ lib/pack.c @@ -1459,8 +1459,8 @@ got_pack_dump_delta_chain_to_mem(uint8_t **outbuf, siz const struct got_error *err = NULL; struct got_delta *delta; uint8_t *base_buf = NULL, *accum_buf = NULL, *delta_buf; - size_t base_bufsz = 0, accum_size = 0, delta_len; - uint64_t max_size; + size_t base_bufsz = 0, accum_bufsz = 0, accum_size = 0, delta_len; + uint64_t max_size = 0; int n = 0; *outbuf = NULL; @@ -1468,16 +1468,10 @@ got_pack_dump_delta_chain_to_mem(uint8_t **outbuf, siz if (STAILQ_EMPTY(&deltas->entries)) return got_error(GOT_ERR_BAD_DELTA_CHAIN); - - err = got_pack_get_delta_chain_max_size(&max_size, deltas, pack); - if (err) - return err; - accum_buf = malloc(max_size); - if (accum_buf == NULL) - return got_error_from_errno("malloc"); /* Deltas are ordered in ascending order. */ STAILQ_FOREACH(delta, &deltas->entries, entry) { + uint64_t base_size, result_size = 0; int cached = 1; if (n == 0) { size_t delta_data_offset; @@ -1496,6 +1490,10 @@ got_pack_dump_delta_chain_to_mem(uint8_t **outbuf, siz err = got_error(GOT_ERR_PACK_OFFSET); goto done; } + + if (delta->size > max_size) + max_size = delta->size; + if (pack->map) { size_t mapoff = (size_t)delta_data_offset; err = got_inflate_to_mem_mmap(&base_buf, @@ -1534,6 +1532,36 @@ got_pack_dump_delta_chain_to_mem(uint8_t **outbuf, siz goto done; } } + + err = got_delta_get_sizes(&base_size, &result_size, + delta_buf, delta_len); + if (err) + goto done; + if (base_size > max_size) + max_size = base_size; + if (result_size > max_size) + max_size = result_size; + + if (max_size > base_bufsz) { + uint8_t *p = realloc(base_buf, max_size); + if (p == NULL) { + err = got_error_from_errno("realloc"); + goto done; + } + base_buf = p; + base_bufsz = max_size; + } + + if (max_size > accum_bufsz) { + uint8_t *p = realloc(accum_buf, max_size); + if (p == NULL) { + err = got_error_from_errno("realloc"); + goto done; + } + accum_buf = p; + accum_bufsz = max_size; + } + err = got_delta_apply_in_mem(base_buf, base_bufsz, delta_buf, delta_len, accum_buf, &accum_size, max_size); @@ -1546,24 +1574,11 @@ got_pack_dump_delta_chain_to_mem(uint8_t **outbuf, siz if (n < deltas->nentries) { /* Accumulated delta becomes the new base. */ uint8_t *tmp = accum_buf; - /* - * Base buffer switches roles with accumulation buffer. - * Ensure it can hold the largest result in the delta - * chain. Initial allocation might have been smaller. - */ - if (base_bufsz < max_size) { - uint8_t *p; - p = reallocarray(base_buf, 1, max_size); - if (p == NULL) { - err = got_error_from_errno( - "reallocarray"); - goto done; - } - base_buf = p; - base_bufsz = max_size; - } + size_t tmp_size = accum_bufsz; accum_buf = base_buf; + accum_bufsz = base_bufsz; base_buf = tmp; + base_bufsz = tmp_size; } }