diff options
author | René Scharfe <l.s.r@web.de> | 2024-12-28 10:47:05 +0100 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2024-12-28 17:00:44 +0100 |
commit | 8db127d43f5b0eff254a851f9c966b7b85d91992 (patch) | |
tree | 8c7cd2c2a66573512ade8f4e80f5af8e88fe1e4b /reftable/block.c | |
parent | Merge https://github.com/j6t/git-gui (diff) | |
download | git-8db127d43f5b0eff254a851f9c966b7b85d91992.tar.xz git-8db127d43f5b0eff254a851f9c966b7b85d91992.zip |
reftable: avoid leaks on realloc error
When realloc(3) fails, it returns NULL and keeps the original allocation
intact. REFTABLE_ALLOC_GROW overwrites both the original pointer and
the allocation count variable in that case, simultaneously leaking the
original allocation and misrepresenting the number of storable items.
parse_names() and reftable_buf_add() avoid leaking by restoring the
original pointer value on failure, but all other callers seem to be OK
with losing the old allocation. Add a new variant of the macro,
REFTABLE_ALLOC_GROW_OR_NULL, which plugs the leak and zeros the
allocation counter. Use it for those callers.
Signed-off-by: René Scharfe <l.s.r@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'reftable/block.c')
-rw-r--r-- | reftable/block.c | 10 |
1 files changed, 6 insertions, 4 deletions
diff --git a/reftable/block.c b/reftable/block.c index 0198078485..9858bbc7c5 100644 --- a/reftable/block.c +++ b/reftable/block.c @@ -53,7 +53,8 @@ static int block_writer_register_restart(struct block_writer *w, int n, if (2 + 3 * rlen + n > w->block_size - w->next) return -1; if (is_restart) { - REFTABLE_ALLOC_GROW(w->restarts, w->restart_len + 1, w->restart_cap); + REFTABLE_ALLOC_GROW_OR_NULL(w->restarts, w->restart_len + 1, + w->restart_cap); if (!w->restarts) return REFTABLE_OUT_OF_MEMORY_ERROR; w->restarts[w->restart_len++] = w->next; @@ -176,7 +177,8 @@ int block_writer_finish(struct block_writer *w) * is guaranteed to return `Z_STREAM_END`. */ compressed_len = deflateBound(w->zstream, src_len); - REFTABLE_ALLOC_GROW(w->compressed, compressed_len, w->compressed_cap); + REFTABLE_ALLOC_GROW_OR_NULL(w->compressed, compressed_len, + w->compressed_cap); if (!w->compressed) { ret = REFTABLE_OUT_OF_MEMORY_ERROR; return ret; @@ -235,8 +237,8 @@ int block_reader_init(struct block_reader *br, struct reftable_block *block, uLong src_len = block->len - block_header_skip; /* Log blocks specify the *uncompressed* size in their header. */ - REFTABLE_ALLOC_GROW(br->uncompressed_data, sz, - br->uncompressed_cap); + REFTABLE_ALLOC_GROW_OR_NULL(br->uncompressed_data, sz, + br->uncompressed_cap); if (!br->uncompressed_data) { err = REFTABLE_OUT_OF_MEMORY_ERROR; goto done; |