aboutsummaryrefslogtreecommitdiffstats
path: root/reftable/basics.c
diff options
context:
space:
mode:
authorRené Scharfe <l.s.r@web.de>2024-12-28 10:48:00 +0100
committerJunio C Hamano <gitster@pobox.com>2024-12-28 08:00:44 -0800
commit2cca185e85171c462166839cfd6ee57c09573160 (patch)
treee768f5c93812fe2976a52319c0454d7c99b75248 /reftable/basics.c
parentreftable: avoid leaks on realloc error (diff)
downloadgit-2cca185e85171c462166839cfd6ee57c09573160.tar.gz
git-2cca185e85171c462166839cfd6ee57c09573160.zip
reftable: fix allocation count 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() avoids the leak by keeping the original pointer if reallocation fails, but still increase the allocation count in such a case as if it succeeded. That's OK, because the error handling code just frees everything and doesn't look at names_cap anymore. reftable_buf_add() does the same, but here it is a problem as it leaves the reftable_buf in a broken state, with ->alloc being roughly twice as big as the actually allocated memory, allowing out-of-bounds writes in subsequent calls. Reimplement REFTABLE_ALLOC_GROW to avoid leaks, keep allocation counts in sync and still signal failures to callers while avoiding code duplication in callers. Make it an expression that evaluates to 0 if no reallocation is needed or it succeeded and 1 on failure while keeping the original pointer and allocation counter values. Adjust REFTABLE_ALLOC_GROW_OR_NULL to the new calling convention for REFTABLE_ALLOC_GROW, but keep its support for non-size_t alloc variables for now. Signed-off-by: René Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to '')
-rw-r--r--reftable/basics.c11
1 files changed, 3 insertions, 8 deletions
diff --git a/reftable/basics.c b/reftable/basics.c
index 70b1091d14..cd6b39dbe9 100644
--- a/reftable/basics.c
+++ b/reftable/basics.c
@@ -124,11 +124,8 @@ int reftable_buf_add(struct reftable_buf *buf, const void *data, size_t len)
size_t newlen = buf->len + len;
if (newlen + 1 > buf->alloc) {
- char *reallocated = buf->buf;
- REFTABLE_ALLOC_GROW(reallocated, newlen + 1, buf->alloc);
- if (!reallocated)
+ if (REFTABLE_ALLOC_GROW(buf->buf, newlen + 1, buf->alloc))
return REFTABLE_OUT_OF_MEMORY_ERROR;
- buf->buf = reallocated;
}
memcpy(buf->buf + buf->len, data, len);
@@ -233,11 +230,9 @@ char **parse_names(char *buf, int size)
next = end;
}
if (p < next) {
- char **names_grown = names;
- REFTABLE_ALLOC_GROW(names_grown, names_len + 1, names_cap);
- if (!names_grown)
+ if (REFTABLE_ALLOC_GROW(names, names_len + 1,
+ names_cap))
goto err;
- names = names_grown;
names[names_len] = reftable_strdup(p);
if (!names[names_len++])