xdiff: handle allocation failure in patience diff

Other users of libxdiff such as libgit2 need to be able to handle
allocation failures. As NULL is a valid return value the function
signature is changed to be able report allocation failures.

Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Phillip Wood 2022-02-16 10:15:07 +00:00 committed by Junio C Hamano
parent 9df0fc3d57
commit 61f883965f

View File

@ -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;
} }