Skip to content

Commit 47be28e

Browse files
committed
Merge branch 'pw/xdiff-alloc-fail'
Improve failure case behaviour of xdiff library when memory allocation fails. * pw/xdiff-alloc-fail: xdiff: handle allocation failure when merging xdiff: refactor a function xdiff: handle allocation failure in patience diff xdiff: fix a memory leak
2 parents 82386b4 + 43ad3af commit 47be28e

File tree

4 files changed

+51
-48
lines changed

4 files changed

+51
-48
lines changed

xdiff/xdiffi.c

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -315,16 +315,19 @@ int xdl_do_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
315315
long *kvd, *kvdf, *kvdb;
316316
xdalgoenv_t xenv;
317317
diffdata_t dd1, dd2;
318+
int res;
318319

319-
if (XDF_DIFF_ALG(xpp->flags) == XDF_PATIENCE_DIFF)
320-
return xdl_do_patience_diff(mf1, mf2, xpp, xe);
321-
322-
if (XDF_DIFF_ALG(xpp->flags) == XDF_HISTOGRAM_DIFF)
323-
return xdl_do_histogram_diff(mf1, mf2, xpp, xe);
320+
if (xdl_prepare_env(mf1, mf2, xpp, xe) < 0)
321+
return -1;
324322

325-
if (xdl_prepare_env(mf1, mf2, xpp, xe) < 0) {
323+
if (XDF_DIFF_ALG(xpp->flags) == XDF_PATIENCE_DIFF) {
324+
res = xdl_do_patience_diff(mf1, mf2, xpp, xe);
325+
goto out;
326+
}
326327

327-
return -1;
328+
if (XDF_DIFF_ALG(xpp->flags) == XDF_HISTOGRAM_DIFF) {
329+
res = xdl_do_histogram_diff(mf1, mf2, xpp, xe);
330+
goto out;
328331
}
329332

330333
/*
@@ -359,17 +362,15 @@ int xdl_do_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
359362
dd2.rchg = xe->xdf2.rchg;
360363
dd2.rindex = xe->xdf2.rindex;
361364

362-
if (xdl_recs_cmp(&dd1, 0, dd1.nrec, &dd2, 0, dd2.nrec,
363-
kvdf, kvdb, (xpp->flags & XDF_NEED_MINIMAL) != 0, &xenv) < 0) {
364-
365-
xdl_free(kvd);
366-
xdl_free_env(xe);
367-
return -1;
368-
}
369-
365+
res = xdl_recs_cmp(&dd1, 0, dd1.nrec, &dd2, 0, dd2.nrec,
366+
kvdf, kvdb, (xpp->flags & XDF_NEED_MINIMAL) != 0,
367+
&xenv);
370368
xdl_free(kvd);
369+
out:
370+
if (res < 0)
371+
xdl_free_env(xe);
371372

372-
return 0;
373+
return res;
373374
}
374375

375376

xdiff/xhistogram.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -372,9 +372,6 @@ static int histogram_diff(xpparam_t const *xpp, xdfenv_t *env,
372372
int xdl_do_histogram_diff(mmfile_t *file1, mmfile_t *file2,
373373
xpparam_t const *xpp, xdfenv_t *env)
374374
{
375-
if (xdl_prepare_env(file1, file2, xpp, env) < 0)
376-
return -1;
377-
378375
return histogram_diff(xpp, env,
379376
env->xdf1.dstart + 1, env->xdf1.dend - env->xdf1.dstart + 1,
380377
env->xdf2.dstart + 1, env->xdf2.dend - env->xdf2.dstart + 1);

xdiff/xmerge.c

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -684,54 +684,56 @@ static int xdl_do_merge(xdfenv_t *xe1, xdchange_t *xscr1,
684684
int xdl_merge(mmfile_t *orig, mmfile_t *mf1, mmfile_t *mf2,
685685
xmparam_t const *xmp, mmbuffer_t *result)
686686
{
687-
xdchange_t *xscr1, *xscr2;
687+
xdchange_t *xscr1 = NULL, *xscr2 = NULL;
688688
xdfenv_t xe1, xe2;
689-
int status;
689+
int status = -1;
690690
xpparam_t const *xpp = &xmp->xpp;
691691

692692
result->ptr = NULL;
693693
result->size = 0;
694694

695-
if (xdl_do_diff(orig, mf1, xpp, &xe1) < 0) {
695+
if (xdl_do_diff(orig, mf1, xpp, &xe1) < 0)
696696
return -1;
697-
}
698-
if (xdl_do_diff(orig, mf2, xpp, &xe2) < 0) {
699-
xdl_free_env(&xe1);
700-
return -1;
701-
}
697+
698+
if (xdl_do_diff(orig, mf2, xpp, &xe2) < 0)
699+
goto free_xe1; /* avoid double free of xe2 */
700+
702701
if (xdl_change_compact(&xe1.xdf1, &xe1.xdf2, xpp->flags) < 0 ||
703702
xdl_change_compact(&xe1.xdf2, &xe1.xdf1, xpp->flags) < 0 ||
704-
xdl_build_script(&xe1, &xscr1) < 0) {
705-
xdl_free_env(&xe1);
706-
return -1;
707-
}
703+
xdl_build_script(&xe1, &xscr1) < 0)
704+
goto out;
705+
708706
if (xdl_change_compact(&xe2.xdf1, &xe2.xdf2, xpp->flags) < 0 ||
709707
xdl_change_compact(&xe2.xdf2, &xe2.xdf1, xpp->flags) < 0 ||
710-
xdl_build_script(&xe2, &xscr2) < 0) {
711-
xdl_free_script(xscr1);
712-
xdl_free_env(&xe1);
713-
xdl_free_env(&xe2);
714-
return -1;
715-
}
716-
status = 0;
708+
xdl_build_script(&xe2, &xscr2) < 0)
709+
goto out;
710+
717711
if (!xscr1) {
718712
result->ptr = xdl_malloc(mf2->size);
713+
if (!result->ptr)
714+
goto out;
715+
status = 0;
719716
memcpy(result->ptr, mf2->ptr, mf2->size);
720717
result->size = mf2->size;
721718
} else if (!xscr2) {
722719
result->ptr = xdl_malloc(mf1->size);
720+
if (!result->ptr)
721+
goto out;
722+
status = 0;
723723
memcpy(result->ptr, mf1->ptr, mf1->size);
724724
result->size = mf1->size;
725725
} else {
726726
status = xdl_do_merge(&xe1, xscr1,
727727
&xe2, xscr2,
728728
xmp, result);
729729
}
730+
out:
730731
xdl_free_script(xscr1);
731732
xdl_free_script(xscr2);
732733

733-
xdl_free_env(&xe1);
734734
xdl_free_env(&xe2);
735+
free_xe1:
736+
xdl_free_env(&xe1);
735737

736738
return status;
737739
}

xdiff/xpatience.c

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ static int binary_search(struct entry **sequence, int longest,
198198
* item per sequence length: the sequence with the smallest last
199199
* element (in terms of line2).
200200
*/
201-
static struct entry *find_longest_common_sequence(struct hashmap *map)
201+
static int find_longest_common_sequence(struct hashmap *map, struct entry **res)
202202
{
203203
struct entry **sequence = xdl_malloc(map->nr * sizeof(struct entry *));
204204
int longest = 0, i;
@@ -211,6 +211,9 @@ static struct entry *find_longest_common_sequence(struct hashmap *map)
211211
*/
212212
int anchor_i = -1;
213213

214+
if (!sequence)
215+
return -1;
216+
214217
for (entry = map->first; entry; entry = entry->next) {
215218
if (!entry->line2 || entry->line2 == NON_UNIQUE)
216219
continue;
@@ -230,8 +233,9 @@ static struct entry *find_longest_common_sequence(struct hashmap *map)
230233

231234
/* No common unique lines were found */
232235
if (!longest) {
236+
*res = NULL;
233237
xdl_free(sequence);
234-
return NULL;
238+
return 0;
235239
}
236240

237241
/* Iterate starting at the last element, adjusting the "next" members */
@@ -241,8 +245,9 @@ static struct entry *find_longest_common_sequence(struct hashmap *map)
241245
entry->previous->next = entry;
242246
entry = entry->previous;
243247
}
248+
*res = entry;
244249
xdl_free(sequence);
245-
return entry;
250+
return 0;
246251
}
247252

248253
static int match(struct hashmap *map, int line1, int line2)
@@ -358,25 +363,23 @@ static int patience_diff(mmfile_t *file1, mmfile_t *file2,
358363
return 0;
359364
}
360365

361-
first = find_longest_common_sequence(&map);
366+
result = find_longest_common_sequence(&map, &first);
367+
if (result)
368+
goto out;
362369
if (first)
363370
result = walk_common_sequence(&map, first,
364371
line1, count1, line2, count2);
365372
else
366373
result = fall_back_to_classic_diff(&map,
367374
line1, count1, line2, count2);
368-
375+
out:
369376
xdl_free(map.entries);
370377
return result;
371378
}
372379

373380
int xdl_do_patience_diff(mmfile_t *file1, mmfile_t *file2,
374381
xpparam_t const *xpp, xdfenv_t *env)
375382
{
376-
if (xdl_prepare_env(file1, file2, xpp, env) < 0)
377-
return -1;
378-
379-
/* environment is cleaned up in xdl_diff() */
380383
return patience_diff(file1, file2, xpp, env,
381384
1, env->xdf1.nrec, 1, env->xdf2.nrec);
382385
}

0 commit comments

Comments
 (0)