xdiff: introduce XDL_ALLOC_ARRAY()

Add a helper to allocate an array that automatically calculates the allocation size. This is analogous to ALLOC_ARRAY() in the rest of the codebase but returns NULL if the allocation fails to accommodate other users of libxdiff such as libgit2. The helper will also return NULL if the multiplication in the allocation calculation overflows. Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Phillip Wood committed Jul 8, 2022 at 16:25 UTC abf04bdaa845a6650d1f44b9f5914df442559d75
4 files changed +12 -7
xdiff/xdiffi.c
+1 -1
@@ -337,7 +337,7 @@ int xdl_do_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
337 * One is to store the forward path and one to store the backward path.
338 */
339 ndiags = xe->xdf1.nreff + xe->xdf2.nreff + 3;
340 - if (!(kvd = (long *) xdl_malloc((2 * ndiags + 2) * sizeof(long)))) {
340 + if (!XDL_ALLOC_ARRAY(kvd, 2 * ndiags + 2)) {
341
342 xdl_free_env(xe);
343 return -1;
xdiff/xmacros.h
+5
@@ -49,5 +49,10 @@ do { \
49 ((unsigned long) __p[2]) << 16 | ((unsigned long) __p[3]) << 24; \
50 } while (0)
51
52 +/* Allocate an array of nr elements, returns NULL on failure */
53 +#define XDL_ALLOC_ARRAY(p, nr) \
54 + ((p) = SIZE_MAX / sizeof(*(p)) >= (size_t)(nr) \
55 + ? xdl_malloc((nr) * sizeof(*(p))) \
56 + : NULL)
57
58 #endif /* #if !defined(XMACROS_H) */
xdiff/xpatience.c
+2 -2
@@ -200,7 +200,7 @@ static int binary_search(struct entry **sequence, int longest,
200 */
201 static int find_longest_common_sequence(struct hashmap *map, struct entry **res)
202 {
203 - struct entry **sequence = xdl_malloc(map->nr * sizeof(struct entry *));
203 + struct entry **sequence;
204 int longest = 0, i;
205 struct entry *entry;
206
@@ -211,7 +211,7 @@ static int find_longest_common_sequence(struct hashmap *map, struct entry **res)
211 */
212 int anchor_i = -1;
213
214 - if (!sequence)
214 + if (!XDL_ALLOC_ARRAY(sequence, map->nr))
215 return -1;
216
217 for (entry = map->first; entry; entry = entry->next) {
xdiff/xprepare.c
+4 -4
@@ -86,7 +86,7 @@ static int xdl_init_classifier(xdlclassifier_t *cf, long size, long flags) {
86 memset(cf->rchash, 0, cf->hsize * sizeof(xdlclass_t *));
87
88 cf->alloc = size;
89 - if (!(cf->rcrecs = (xdlclass_t **) xdl_malloc(cf->alloc * sizeof(xdlclass_t *)))) {
89 + if (!XDL_ALLOC_ARRAY(cf->rcrecs, cf->alloc)) {
90
91 xdl_free(cf->rchash);
92 xdl_cha_free(&cf->ncha);
@@ -178,7 +178,7 @@ static int xdl_prepare_ctx(unsigned int pass, mmfile_t *mf, long narec, xpparam_
178
179 if (xdl_cha_init(&xdf->rcha, sizeof(xrecord_t), narec / 4 + 1) < 0)
180 goto abort;
181 - if (!(recs = (xrecord_t **) xdl_malloc(narec * sizeof(xrecord_t *))))
181 + if (!XDL_ALLOC_ARRAY(recs, narec))
182 goto abort;
183
184 hbits = xdl_hashbits((unsigned int) narec);
@@ -215,9 +215,9 @@ static int xdl_prepare_ctx(unsigned int pass, mmfile_t *mf, long narec, xpparam_
215
216 if ((XDF_DIFF_ALG(xpp->flags) != XDF_PATIENCE_DIFF) &&
217 (XDF_DIFF_ALG(xpp->flags) != XDF_HISTOGRAM_DIFF)) {
218 - if (!(rindex = xdl_malloc((nrec + 1) * sizeof(*rindex))))
218 + if (!XDL_ALLOC_ARRAY(rindex, nrec + 1))
219 goto abort;
220 - if (!(ha = xdl_malloc((nrec + 1) * sizeof(*ha))))
220 + if (!XDL_ALLOC_ARRAY(ha, nrec + 1))
221 goto abort;
222 }
223