]> git.ipfire.org Git - thirdparty/git.git/commitdiff
reftable/basics: stop using `st_mult()` in array allocators
authorPatrick Steinhardt <ps@pks.im>
Tue, 18 Feb 2025 09:20:44 +0000 (10:20 +0100)
committerJunio C Hamano <gitster@pobox.com>
Tue, 18 Feb 2025 18:55:37 +0000 (10:55 -0800)
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>
reftable/basics.h

index a2a010a0e199ba713982c8da7c469cb7fee6a596..646f8d67f2d4decab34c5d508d33f03fbbf6a988 100644 (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;