Skip to content

Commit 5ed69ca

Browse files
committed
Merge branch 'rs/apply-fuzzy-match-fix'
A fix for an ancient bug in "git apply --ignore-space-change" codepath. * rs/apply-fuzzy-match-fix: apply: avoid out-of-bounds access in fuzzy_matchlines()
2 parents 1a5f2e4 + 6ce15ce commit 5ed69ca

File tree

1 file changed

+20
-39
lines changed

1 file changed

+20
-39
lines changed

apply.c

Lines changed: 20 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -300,52 +300,33 @@ static uint32_t hash_line(const char *cp, size_t len)
300300
static int fuzzy_matchlines(const char *s1, size_t n1,
301301
const char *s2, size_t n2)
302302
{
303-
const char *last1 = s1 + n1 - 1;
304-
const char *last2 = s2 + n2 - 1;
305-
int result = 0;
303+
const char *end1 = s1 + n1;
304+
const char *end2 = s2 + n2;
306305

307306
/* ignore line endings */
308-
while ((*last1 == '\r') || (*last1 == '\n'))
309-
last1--;
310-
while ((*last2 == '\r') || (*last2 == '\n'))
311-
last2--;
312-
313-
/* skip leading whitespaces, if both begin with whitespace */
314-
if (s1 <= last1 && s2 <= last2 && isspace(*s1) && isspace(*s2)) {
315-
while (isspace(*s1) && (s1 <= last1))
316-
s1++;
317-
while (isspace(*s2) && (s2 <= last2))
318-
s2++;
319-
}
320-
/* early return if both lines are empty */
321-
if ((s1 > last1) && (s2 > last2))
322-
return 1;
323-
while (!result) {
324-
result = *s1++ - *s2++;
325-
/*
326-
* Skip whitespace inside. We check for whitespace on
327-
* both buffers because we don't want "a b" to match
328-
* "ab"
329-
*/
330-
if (isspace(*s1) && isspace(*s2)) {
331-
while (isspace(*s1) && s1 <= last1)
307+
while (s1 < end1 && (end1[-1] == '\r' || end1[-1] == '\n'))
308+
end1--;
309+
while (s2 < end2 && (end2[-1] == '\r' || end2[-1] == '\n'))
310+
end2--;
311+
312+
while (s1 < end1 && s2 < end2) {
313+
if (isspace(*s1)) {
314+
/*
315+
* Skip whitespace. We check on both buffers
316+
* because we don't want "a b" to match "ab".
317+
*/
318+
if (!isspace(*s2))
319+
return 0;
320+
while (s1 < end1 && isspace(*s1))
332321
s1++;
333-
while (isspace(*s2) && s2 <= last2)
322+
while (s2 < end2 && isspace(*s2))
334323
s2++;
335-
}
336-
/*
337-
* If we reached the end on one side only,
338-
* lines don't match
339-
*/
340-
if (
341-
((s2 > last2) && (s1 <= last1)) ||
342-
((s1 > last1) && (s2 <= last2)))
324+
} else if (*s1++ != *s2++)
343325
return 0;
344-
if ((s1 > last1) && (s2 > last2))
345-
break;
346326
}
347327

348-
return !result;
328+
/* If we reached the end on one side only, lines don't match. */
329+
return s1 == end1 && s2 == end2;
349330
}
350331

351332
static void add_line_info(struct image *img, const char *bol, size_t len, unsigned flag)

0 commit comments

Comments
 (0)