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
This commit is contained in:
commit
47be28e51e
@ -315,16 +315,19 @@ int xdl_do_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
|
|||||||
long *kvd, *kvdf, *kvdb;
|
long *kvd, *kvdf, *kvdb;
|
||||||
xdalgoenv_t xenv;
|
xdalgoenv_t xenv;
|
||||||
diffdata_t dd1, dd2;
|
diffdata_t dd1, dd2;
|
||||||
|
int res;
|
||||||
|
|
||||||
if (XDF_DIFF_ALG(xpp->flags) == XDF_PATIENCE_DIFF)
|
if (xdl_prepare_env(mf1, mf2, xpp, xe) < 0)
|
||||||
return xdl_do_patience_diff(mf1, mf2, xpp, xe);
|
|
||||||
|
|
||||||
if (XDF_DIFF_ALG(xpp->flags) == XDF_HISTOGRAM_DIFF)
|
|
||||||
return xdl_do_histogram_diff(mf1, mf2, xpp, xe);
|
|
||||||
|
|
||||||
if (xdl_prepare_env(mf1, mf2, xpp, xe) < 0) {
|
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if (XDF_DIFF_ALG(xpp->flags) == XDF_PATIENCE_DIFF) {
|
||||||
|
res = xdl_do_patience_diff(mf1, mf2, xpp, xe);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (XDF_DIFF_ALG(xpp->flags) == XDF_HISTOGRAM_DIFF) {
|
||||||
|
res = xdl_do_histogram_diff(mf1, mf2, xpp, xe);
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -359,17 +362,15 @@ int xdl_do_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
|
|||||||
dd2.rchg = xe->xdf2.rchg;
|
dd2.rchg = xe->xdf2.rchg;
|
||||||
dd2.rindex = xe->xdf2.rindex;
|
dd2.rindex = xe->xdf2.rindex;
|
||||||
|
|
||||||
if (xdl_recs_cmp(&dd1, 0, dd1.nrec, &dd2, 0, dd2.nrec,
|
res = xdl_recs_cmp(&dd1, 0, dd1.nrec, &dd2, 0, dd2.nrec,
|
||||||
kvdf, kvdb, (xpp->flags & XDF_NEED_MINIMAL) != 0, &xenv) < 0) {
|
kvdf, kvdb, (xpp->flags & XDF_NEED_MINIMAL) != 0,
|
||||||
|
&xenv);
|
||||||
xdl_free(kvd);
|
xdl_free(kvd);
|
||||||
|
out:
|
||||||
|
if (res < 0)
|
||||||
xdl_free_env(xe);
|
xdl_free_env(xe);
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
xdl_free(kvd);
|
return res;
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -372,9 +372,6 @@ out:
|
|||||||
int xdl_do_histogram_diff(mmfile_t *file1, mmfile_t *file2,
|
int xdl_do_histogram_diff(mmfile_t *file1, mmfile_t *file2,
|
||||||
xpparam_t const *xpp, xdfenv_t *env)
|
xpparam_t const *xpp, xdfenv_t *env)
|
||||||
{
|
{
|
||||||
if (xdl_prepare_env(file1, file2, xpp, env) < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return histogram_diff(xpp, env,
|
return histogram_diff(xpp, env,
|
||||||
env->xdf1.dstart + 1, env->xdf1.dend - env->xdf1.dstart + 1,
|
env->xdf1.dstart + 1, env->xdf1.dend - env->xdf1.dstart + 1,
|
||||||
env->xdf2.dstart + 1, env->xdf2.dend - env->xdf2.dstart + 1);
|
env->xdf2.dstart + 1, env->xdf2.dend - env->xdf2.dstart + 1);
|
||||||
|
@ -684,42 +684,42 @@ static int xdl_do_merge(xdfenv_t *xe1, xdchange_t *xscr1,
|
|||||||
int xdl_merge(mmfile_t *orig, mmfile_t *mf1, mmfile_t *mf2,
|
int xdl_merge(mmfile_t *orig, mmfile_t *mf1, mmfile_t *mf2,
|
||||||
xmparam_t const *xmp, mmbuffer_t *result)
|
xmparam_t const *xmp, mmbuffer_t *result)
|
||||||
{
|
{
|
||||||
xdchange_t *xscr1, *xscr2;
|
xdchange_t *xscr1 = NULL, *xscr2 = NULL;
|
||||||
xdfenv_t xe1, xe2;
|
xdfenv_t xe1, xe2;
|
||||||
int status;
|
int status = -1;
|
||||||
xpparam_t const *xpp = &xmp->xpp;
|
xpparam_t const *xpp = &xmp->xpp;
|
||||||
|
|
||||||
result->ptr = NULL;
|
result->ptr = NULL;
|
||||||
result->size = 0;
|
result->size = 0;
|
||||||
|
|
||||||
if (xdl_do_diff(orig, mf1, xpp, &xe1) < 0) {
|
if (xdl_do_diff(orig, mf1, xpp, &xe1) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
if (xdl_do_diff(orig, mf2, xpp, &xe2) < 0) {
|
if (xdl_do_diff(orig, mf2, xpp, &xe2) < 0)
|
||||||
xdl_free_env(&xe1);
|
goto free_xe1; /* avoid double free of xe2 */
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (xdl_change_compact(&xe1.xdf1, &xe1.xdf2, xpp->flags) < 0 ||
|
if (xdl_change_compact(&xe1.xdf1, &xe1.xdf2, xpp->flags) < 0 ||
|
||||||
xdl_change_compact(&xe1.xdf2, &xe1.xdf1, xpp->flags) < 0 ||
|
xdl_change_compact(&xe1.xdf2, &xe1.xdf1, xpp->flags) < 0 ||
|
||||||
xdl_build_script(&xe1, &xscr1) < 0) {
|
xdl_build_script(&xe1, &xscr1) < 0)
|
||||||
xdl_free_env(&xe1);
|
goto out;
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (xdl_change_compact(&xe2.xdf1, &xe2.xdf2, xpp->flags) < 0 ||
|
if (xdl_change_compact(&xe2.xdf1, &xe2.xdf2, xpp->flags) < 0 ||
|
||||||
xdl_change_compact(&xe2.xdf2, &xe2.xdf1, xpp->flags) < 0 ||
|
xdl_change_compact(&xe2.xdf2, &xe2.xdf1, xpp->flags) < 0 ||
|
||||||
xdl_build_script(&xe2, &xscr2) < 0) {
|
xdl_build_script(&xe2, &xscr2) < 0)
|
||||||
xdl_free_script(xscr1);
|
goto out;
|
||||||
xdl_free_env(&xe1);
|
|
||||||
xdl_free_env(&xe2);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
status = 0;
|
|
||||||
if (!xscr1) {
|
if (!xscr1) {
|
||||||
result->ptr = xdl_malloc(mf2->size);
|
result->ptr = xdl_malloc(mf2->size);
|
||||||
|
if (!result->ptr)
|
||||||
|
goto out;
|
||||||
|
status = 0;
|
||||||
memcpy(result->ptr, mf2->ptr, mf2->size);
|
memcpy(result->ptr, mf2->ptr, mf2->size);
|
||||||
result->size = mf2->size;
|
result->size = mf2->size;
|
||||||
} else if (!xscr2) {
|
} else if (!xscr2) {
|
||||||
result->ptr = xdl_malloc(mf1->size);
|
result->ptr = xdl_malloc(mf1->size);
|
||||||
|
if (!result->ptr)
|
||||||
|
goto out;
|
||||||
|
status = 0;
|
||||||
memcpy(result->ptr, mf1->ptr, mf1->size);
|
memcpy(result->ptr, mf1->ptr, mf1->size);
|
||||||
result->size = mf1->size;
|
result->size = mf1->size;
|
||||||
} else {
|
} else {
|
||||||
@ -727,11 +727,13 @@ int xdl_merge(mmfile_t *orig, mmfile_t *mf1, mmfile_t *mf2,
|
|||||||
&xe2, xscr2,
|
&xe2, xscr2,
|
||||||
xmp, result);
|
xmp, result);
|
||||||
}
|
}
|
||||||
|
out:
|
||||||
xdl_free_script(xscr1);
|
xdl_free_script(xscr1);
|
||||||
xdl_free_script(xscr2);
|
xdl_free_script(xscr2);
|
||||||
|
|
||||||
xdl_free_env(&xe1);
|
|
||||||
xdl_free_env(&xe2);
|
xdl_free_env(&xe2);
|
||||||
|
free_xe1:
|
||||||
|
xdl_free_env(&xe1);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -198,7 +198,7 @@ static int binary_search(struct entry **sequence, int longest,
|
|||||||
* item per sequence length: the sequence with the smallest last
|
* item per sequence length: the sequence with the smallest last
|
||||||
* element (in terms of line2).
|
* element (in terms of line2).
|
||||||
*/
|
*/
|
||||||
static struct entry *find_longest_common_sequence(struct hashmap *map)
|
static int find_longest_common_sequence(struct hashmap *map, struct entry **res)
|
||||||
{
|
{
|
||||||
struct entry **sequence = xdl_malloc(map->nr * sizeof(struct entry *));
|
struct entry **sequence = xdl_malloc(map->nr * sizeof(struct entry *));
|
||||||
int longest = 0, i;
|
int longest = 0, i;
|
||||||
@ -211,6 +211,9 @@ static struct entry *find_longest_common_sequence(struct hashmap *map)
|
|||||||
*/
|
*/
|
||||||
int anchor_i = -1;
|
int anchor_i = -1;
|
||||||
|
|
||||||
|
if (!sequence)
|
||||||
|
return -1;
|
||||||
|
|
||||||
for (entry = map->first; entry; entry = entry->next) {
|
for (entry = map->first; entry; entry = entry->next) {
|
||||||
if (!entry->line2 || entry->line2 == NON_UNIQUE)
|
if (!entry->line2 || entry->line2 == NON_UNIQUE)
|
||||||
continue;
|
continue;
|
||||||
@ -230,8 +233,9 @@ static struct entry *find_longest_common_sequence(struct hashmap *map)
|
|||||||
|
|
||||||
/* No common unique lines were found */
|
/* No common unique lines were found */
|
||||||
if (!longest) {
|
if (!longest) {
|
||||||
|
*res = NULL;
|
||||||
xdl_free(sequence);
|
xdl_free(sequence);
|
||||||
return NULL;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Iterate starting at the last element, adjusting the "next" members */
|
/* Iterate starting at the last element, adjusting the "next" members */
|
||||||
@ -241,8 +245,9 @@ static struct entry *find_longest_common_sequence(struct hashmap *map)
|
|||||||
entry->previous->next = entry;
|
entry->previous->next = entry;
|
||||||
entry = entry->previous;
|
entry = entry->previous;
|
||||||
}
|
}
|
||||||
|
*res = entry;
|
||||||
xdl_free(sequence);
|
xdl_free(sequence);
|
||||||
return entry;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int match(struct hashmap *map, int line1, int line2)
|
static int match(struct hashmap *map, int line1, int line2)
|
||||||
@ -358,14 +363,16 @@ static int patience_diff(mmfile_t *file1, mmfile_t *file2,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
first = find_longest_common_sequence(&map);
|
result = find_longest_common_sequence(&map, &first);
|
||||||
|
if (result)
|
||||||
|
goto out;
|
||||||
if (first)
|
if (first)
|
||||||
result = walk_common_sequence(&map, first,
|
result = walk_common_sequence(&map, first,
|
||||||
line1, count1, line2, count2);
|
line1, count1, line2, count2);
|
||||||
else
|
else
|
||||||
result = fall_back_to_classic_diff(&map,
|
result = fall_back_to_classic_diff(&map,
|
||||||
line1, count1, line2, count2);
|
line1, count1, line2, count2);
|
||||||
|
out:
|
||||||
xdl_free(map.entries);
|
xdl_free(map.entries);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -373,10 +380,6 @@ static int patience_diff(mmfile_t *file1, mmfile_t *file2,
|
|||||||
int xdl_do_patience_diff(mmfile_t *file1, mmfile_t *file2,
|
int xdl_do_patience_diff(mmfile_t *file1, mmfile_t *file2,
|
||||||
xpparam_t const *xpp, xdfenv_t *env)
|
xpparam_t const *xpp, xdfenv_t *env)
|
||||||
{
|
{
|
||||||
if (xdl_prepare_env(file1, file2, xpp, env) < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* environment is cleaned up in xdl_diff() */
|
|
||||||
return patience_diff(file1, file2, xpp, env,
|
return patience_diff(file1, file2, xpp, env,
|
||||||
1, env->xdf1.nrec, 1, env->xdf2.nrec);
|
1, env->xdf1.nrec, 1, env->xdf2.nrec);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user