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>
Patrick Steinhardt committed
Feb 18, 2025 at 10:20 UTC
6e3ea71639a3541523f2be8f950325c8a0aa6768
1 file changed
+32
-4
reftable/basics.h
+32
-4
@@ -117,18 +117,46 @@ void reftable_free(void *p);
117
void *reftable_calloc(size_t nelem, size_t elsize);
118
char *reftable_strdup(const char *str);
119
120
-#define REFTABLE_ALLOC_ARRAY(x, alloc) (x) = reftable_malloc(st_mult(sizeof(*(x)), (alloc)))
120
+static inline int reftable_alloc_size(size_t nelem, size_t elsize, size_t *out)
121
+{
122
+ if (nelem && elsize > SIZE_MAX / nelem)
123
+ return -1;
124
+ *out = nelem * elsize;
125
+ return 0;
126
+}
127
+
128
+#define REFTABLE_ALLOC_ARRAY(x, alloc) do { \
129
+ size_t alloc_size; \
130
+ if (reftable_alloc_size(sizeof(*(x)), (alloc), &alloc_size) < 0) { \
131
+ errno = ENOMEM; \
132
+ (x) = NULL; \
133
+ } else { \
134
+ (x) = reftable_malloc(alloc_size); \
135
+ } \
136
+ } while (0)
137
#define REFTABLE_CALLOC_ARRAY(x, alloc) (x) = reftable_calloc((alloc), sizeof(*(x)))
122
-#define REFTABLE_REALLOC_ARRAY(x, alloc) (x) = reftable_realloc((x), st_mult(sizeof(*(x)), (alloc)))
138
+#define REFTABLE_REALLOC_ARRAY(x, alloc) do { \
139
+ size_t alloc_size; \
140
+ if (reftable_alloc_size(sizeof(*(x)), (alloc), &alloc_size) < 0) { \
141
+ errno = ENOMEM; \
142
+ (x) = NULL; \
143
+ } else { \
144
+ (x) = reftable_realloc((x), alloc_size); \
145
+ } \
146
+ } while (0)
147
148
static inline void *reftable_alloc_grow(void *p, size_t nelem, size_t elsize,
149
size_t *allocp)
150
{
151
void *new_p;
128
- size_t alloc = *allocp * 2 + 1;
152
+ size_t alloc = *allocp * 2 + 1, alloc_bytes;
153
if (alloc < nelem)
154
alloc = nelem;
131
- new_p = reftable_realloc(p, st_mult(elsize, alloc));
155
+ if (reftable_alloc_size(elsize, alloc, &alloc_bytes) < 0) {
156
+ errno = ENOMEM;
157
+ return p;
158
+ }
159
+ new_p = reftable_realloc(p, alloc_bytes);
160
if (!new_p)
161
return p;
162
*allocp = alloc;