reftable/basics: stop using `st_mult()` in array allocators

We're using `st_mult()` as part of our macro helpers that allocate
arrays. This is bad due two two reasons:

  - `st_mult()` causes us to die in case the multiplication overflows.

  - `st_mult()` ties us to the Git codebase.

Refactor the code to instead detect overflows manually and return an
error in such cases.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
main
Patrick Steinhardt 2025-02-18 10:20:44 +01:00 committed by Junio C Hamano
parent 445f9f4f35
commit 6e3ea71639
1 changed files with 32 additions and 4 deletions

View File

@ -117,18 +117,46 @@ void reftable_free(void *p);
void *reftable_calloc(size_t nelem, size_t elsize);
char *reftable_strdup(const char *str);

#define REFTABLE_ALLOC_ARRAY(x, alloc) (x) = reftable_malloc(st_mult(sizeof(*(x)), (alloc)))
static inline int reftable_alloc_size(size_t nelem, size_t elsize, size_t *out)
{
if (nelem && elsize > SIZE_MAX / nelem)
return -1;
*out = nelem * elsize;
return 0;
}

#define REFTABLE_ALLOC_ARRAY(x, alloc) do { \
size_t alloc_size; \
if (reftable_alloc_size(sizeof(*(x)), (alloc), &alloc_size) < 0) { \
errno = ENOMEM; \
(x) = NULL; \
} else { \
(x) = reftable_malloc(alloc_size); \
} \
} while (0)
#define REFTABLE_CALLOC_ARRAY(x, alloc) (x) = reftable_calloc((alloc), sizeof(*(x)))
#define REFTABLE_REALLOC_ARRAY(x, alloc) (x) = reftable_realloc((x), st_mult(sizeof(*(x)), (alloc)))
#define REFTABLE_REALLOC_ARRAY(x, alloc) do { \
size_t alloc_size; \
if (reftable_alloc_size(sizeof(*(x)), (alloc), &alloc_size) < 0) { \
errno = ENOMEM; \
(x) = NULL; \
} else { \
(x) = reftable_realloc((x), alloc_size); \
} \
} while (0)

static inline void *reftable_alloc_grow(void *p, size_t nelem, size_t elsize,
size_t *allocp)
{
void *new_p;
size_t alloc = *allocp * 2 + 1;
size_t alloc = *allocp * 2 + 1, alloc_bytes;
if (alloc < nelem)
alloc = nelem;
new_p = reftable_realloc(p, st_mult(elsize, alloc));
if (reftable_alloc_size(elsize, alloc, &alloc_bytes) < 0) {
errno = ENOMEM;
return p;
}
new_p = reftable_realloc(p, alloc_bytes);
if (!new_p)
return p;
*allocp = alloc;