commit 6c85883bcc71c13fe4fa5bfba2ddf30edabc92b9 from: Stefan Sperling via: Thomas Adam date: Tue May 31 23:14:47 2022 UTC avoid get_delta_chain_max_size() in dump_delta_chain_to_mem() commit - 210941d5b54452c8d6c17e171bae6b701622a014 commit + 6c85883bcc71c13fe4fa5bfba2ddf30edabc92b9 blob - 5c41b9f15c9dcf5b1f2cb329af87e3d94e61a8e1 blob + 63393465efc849fc14e7a08eb628b52349ce399d --- lib/pack.c +++ lib/pack.c @@ -1455,8 +1455,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; @@ -1464,16 +1464,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; @@ -1492,6 +1486,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, @@ -1530,6 +1528,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); @@ -1542,24 +1570,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; } }