Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.kernel.org/pub/scm/git/git.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/xdiff
diff options
context:
space:
mode:
authorPhillip Wood <phillip.wood@dunelm.org.uk>2022-07-08 19:25:19 +0300
committerJunio C Hamano <gitster@pobox.com>2022-07-08 19:34:30 +0300
commitf7b587bf656574103a0a2ad9c2337b0d15c0e92d (patch)
tree00bc34a5d6773022acd2a3a9434d50b7a9dc073a /xdiff
parent848fd5ae5b6506df50ae872302d94b794dc57d51 (diff)
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 <phillip.wood@dunelm.org.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'xdiff')
-rw-r--r--xdiff/xmacros.h10
-rw-r--r--xdiff/xprepare.c19
-rw-r--r--xdiff/xutils.c17
-rw-r--r--xdiff/xutils.h3
4 files changed, 33 insertions, 16 deletions
diff --git a/xdiff/xmacros.h b/xdiff/xmacros.h
index 0977d1615a..8487bb396f 100644
--- a/xdiff/xmacros.h
+++ b/xdiff/xmacros.h
@@ -58,4 +58,14 @@ do { \
/* Allocate an array of nr zeroed out elements, returns NULL on failure */
#define XDL_CALLOC_ARRAY(p, nr) ((p) = xdl_calloc(nr, sizeof(*(p))))
+/*
+ * Ensure array p can accommodate at least nr elements, growing the
+ * array and updating alloc (which is the number of allocated
+ * elements) as necessary. Frees p and returns -1 on failure, returns
+ * 0 on success
+ */
+#define XDL_ALLOC_GROW(p, nr, alloc) \
+ (-!((nr) <= (alloc) || \
+ ((p) = xdl_alloc_grow_helper((p), (nr), &(alloc), sizeof(*(p))))))
+
#endif /* #if !defined(XMACROS_H) */
diff --git a/xdiff/xprepare.c b/xdiff/xprepare.c
index b016570c48..c84549f6c5 100644
--- a/xdiff/xprepare.c
+++ b/xdiff/xprepare.c
@@ -111,7 +111,6 @@ static int xdl_classify_record(unsigned int pass, xdlclassifier_t *cf, xrecord_t
long hi;
char const *line;
xdlclass_t *rcrec;
- xdlclass_t **rcrecs;
line = rec->ptr;
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
return -1;
}
rcrec->idx = cf->count++;
- if (cf->count > cf->alloc) {
- cf->alloc *= 2;
- if (!(rcrecs = (xdlclass_t **) xdl_realloc(cf->rcrecs, cf->alloc * sizeof(xdlclass_t *)))) {
-
+ if (XDL_ALLOC_GROW(cf->rcrecs, cf->count, cf->alloc))
return -1;
- }
- cf->rcrecs = rcrecs;
- }
cf->rcrecs[rcrec->idx] = rcrec;
rcrec->line = line;
rcrec->size = rec->size;
@@ -163,7 +156,7 @@ static int xdl_prepare_ctx(unsigned int pass, mmfile_t *mf, long narec, xpparam_
unsigned long hav;
char const *blk, *cur, *top, *prev;
xrecord_t *crec;
- xrecord_t **recs, **rrecs;
+ xrecord_t **recs;
xrecord_t **rhash;
unsigned long *ha;
char *rchg;
@@ -190,12 +183,8 @@ static int xdl_prepare_ctx(unsigned int pass, mmfile_t *mf, long narec, xpparam_
for (top = blk + bsize; cur < top; ) {
prev = cur;
hav = xdl_hash_record(&cur, top, xpp->flags);
- if (nrec >= narec) {
- narec *= 2;
- if (!(rrecs = (xrecord_t **) xdl_realloc(recs, narec * sizeof(xrecord_t *))))
- goto abort;
- recs = rrecs;
- }
+ if (XDL_ALLOC_GROW(recs, nrec + 1, narec))
+ goto abort;
if (!(crec = xdl_cha_alloc(&xdf->rcha)))
goto abort;
crec->ptr = prev;
diff --git a/xdiff/xutils.c b/xdiff/xutils.c
index 115b2b1640..9e36f24875 100644
--- a/xdiff/xutils.c
+++ b/xdiff/xutils.c
@@ -432,3 +432,20 @@ int xdl_fall_back_diff(xdfenv_t *diff_env, xpparam_t const *xpp,
return 0;
}
+
+void* xdl_alloc_grow_helper(void *p, long nr, long *alloc, size_t size)
+{
+ void *tmp = NULL;
+ size_t n = ((LONG_MAX - 16) / 2 >= *alloc) ? 2 * *alloc + 16 : LONG_MAX;
+ if (nr > n)
+ n = nr;
+ if (SIZE_MAX / size >= n)
+ tmp = xdl_realloc(p, n * size);
+ if (tmp) {
+ *alloc = n;
+ } else {
+ xdl_free(p);
+ *alloc = 0;
+ }
+ return tmp;
+}
diff --git a/xdiff/xutils.h b/xdiff/xutils.h
index fba7bae03c..fd0bba94e8 100644
--- a/xdiff/xutils.h
+++ b/xdiff/xutils.h
@@ -42,6 +42,7 @@ int xdl_emit_hunk_hdr(long s1, long c1, long s2, long c2,
int xdl_fall_back_diff(xdfenv_t *diff_env, xpparam_t const *xpp,
int line1, int count1, int line2, int count2);
-
+/* Do not call this function, use XDL_ALLOC_GROW instead */
+void* xdl_alloc_grow_helper(void* p, long nr, long* alloc, size_t size);
#endif /* #if !defined(XUTILS_H) */