Skip to content

Commit f7b587b

Browse files
phillipwoodgitster
authored andcommitted
xdiff: introduce XDL_ALLOC_GROW()
Add a helper to grow an array. This is analogous to ALLOC_GROW() in the rest of the codebase but returns −1 on allocation failure to accommodate other users of libxdiff such as libgit2. It will also return a error if the multiplication overflows while calculating the new allocation size. Note that this keeps doubling on reallocation like the code it is replacing rather than increasing the existing size by half like ALLOC_GROW(). It does however copy ALLOC_GROW()'s trick of adding a small amount to the new allocation to avoid a lot of reallocations at small sizes. Note that xdl_alloc_grow_helper() uses long rather than size_t for `nr` and `alloc` to match the existing code. Signed-off-by: Phillip Wood <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 848fd5a commit f7b587b

File tree

4 files changed

+33
-16
lines changed

4 files changed

+33
-16
lines changed

xdiff/xmacros.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,14 @@ do { \
5858
/* Allocate an array of nr zeroed out elements, returns NULL on failure */
5959
#define XDL_CALLOC_ARRAY(p, nr) ((p) = xdl_calloc(nr, sizeof(*(p))))
6060

61+
/*
62+
* Ensure array p can accommodate at least nr elements, growing the
63+
* array and updating alloc (which is the number of allocated
64+
* elements) as necessary. Frees p and returns -1 on failure, returns
65+
* 0 on success
66+
*/
67+
#define XDL_ALLOC_GROW(p, nr, alloc) \
68+
(-!((nr) <= (alloc) || \
69+
((p) = xdl_alloc_grow_helper((p), (nr), &(alloc), sizeof(*(p))))))
70+
6171
#endif /* #if !defined(XMACROS_H) */

xdiff/xprepare.c

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,6 @@ static int xdl_classify_record(unsigned int pass, xdlclassifier_t *cf, xrecord_t
111111
long hi;
112112
char const *line;
113113
xdlclass_t *rcrec;
114-
xdlclass_t **rcrecs;
115114

116115
line = rec->ptr;
117116
hi = (long) XDL_HASHLONG(rec->ha, cf->hbits);
@@ -127,14 +126,8 @@ static int xdl_classify_record(unsigned int pass, xdlclassifier_t *cf, xrecord_t
127126
return -1;
128127
}
129128
rcrec->idx = cf->count++;
130-
if (cf->count > cf->alloc) {
131-
cf->alloc *= 2;
132-
if (!(rcrecs = (xdlclass_t **) xdl_realloc(cf->rcrecs, cf->alloc * sizeof(xdlclass_t *)))) {
133-
129+
if (XDL_ALLOC_GROW(cf->rcrecs, cf->count, cf->alloc))
134130
return -1;
135-
}
136-
cf->rcrecs = rcrecs;
137-
}
138131
cf->rcrecs[rcrec->idx] = rcrec;
139132
rcrec->line = line;
140133
rcrec->size = rec->size;
@@ -163,7 +156,7 @@ static int xdl_prepare_ctx(unsigned int pass, mmfile_t *mf, long narec, xpparam_
163156
unsigned long hav;
164157
char const *blk, *cur, *top, *prev;
165158
xrecord_t *crec;
166-
xrecord_t **recs, **rrecs;
159+
xrecord_t **recs;
167160
xrecord_t **rhash;
168161
unsigned long *ha;
169162
char *rchg;
@@ -190,12 +183,8 @@ static int xdl_prepare_ctx(unsigned int pass, mmfile_t *mf, long narec, xpparam_
190183
for (top = blk + bsize; cur < top; ) {
191184
prev = cur;
192185
hav = xdl_hash_record(&cur, top, xpp->flags);
193-
if (nrec >= narec) {
194-
narec *= 2;
195-
if (!(rrecs = (xrecord_t **) xdl_realloc(recs, narec * sizeof(xrecord_t *))))
196-
goto abort;
197-
recs = rrecs;
198-
}
186+
if (XDL_ALLOC_GROW(recs, nrec + 1, narec))
187+
goto abort;
199188
if (!(crec = xdl_cha_alloc(&xdf->rcha)))
200189
goto abort;
201190
crec->ptr = prev;

xdiff/xutils.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,3 +432,20 @@ int xdl_fall_back_diff(xdfenv_t *diff_env, xpparam_t const *xpp,
432432

433433
return 0;
434434
}
435+
436+
void* xdl_alloc_grow_helper(void *p, long nr, long *alloc, size_t size)
437+
{
438+
void *tmp = NULL;
439+
size_t n = ((LONG_MAX - 16) / 2 >= *alloc) ? 2 * *alloc + 16 : LONG_MAX;
440+
if (nr > n)
441+
n = nr;
442+
if (SIZE_MAX / size >= n)
443+
tmp = xdl_realloc(p, n * size);
444+
if (tmp) {
445+
*alloc = n;
446+
} else {
447+
xdl_free(p);
448+
*alloc = 0;
449+
}
450+
return tmp;
451+
}

xdiff/xutils.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ int xdl_emit_hunk_hdr(long s1, long c1, long s2, long c2,
4242
int xdl_fall_back_diff(xdfenv_t *diff_env, xpparam_t const *xpp,
4343
int line1, int count1, int line2, int count2);
4444

45-
45+
/* Do not call this function, use XDL_ALLOC_GROW instead */
46+
void* xdl_alloc_grow_helper(void* p, long nr, long* alloc, size_t size);
4647

4748
#endif /* #if !defined(XUTILS_H) */

0 commit comments

Comments
 (0)