summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLibravatar Junio C Hamano <gitster@pobox.com>2017-11-21 14:07:52 +0900
committerLibravatar Junio C Hamano <gitster@pobox.com>2017-11-21 14:07:52 +0900
commit5ed69ca6dbcef6122d90b9b8fb9a1b1f65208a6d (patch)
tree6cc93ae1b60d537bd4293845e6cadd29b8395265
parentMerge branch 'ad/submitting-patches-title-decoration' (diff)
parentapply: avoid out-of-bounds access in fuzzy_matchlines() (diff)
downloadtgif-5ed69ca6dbcef6122d90b9b8fb9a1b1f65208a6d.tar.xz
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()
-rw-r--r--apply.c59
1 files changed, 20 insertions, 39 deletions
diff --git a/apply.c b/apply.c
index d676debd59..b8087bd29c 100644
--- a/apply.c
+++ b/apply.c
@@ -300,52 +300,33 @@ static uint32_t hash_line(const char *cp, size_t len)
static int fuzzy_matchlines(const char *s1, size_t n1,
const char *s2, size_t n2)
{
- const char *last1 = s1 + n1 - 1;
- const char *last2 = s2 + n2 - 1;
- int result = 0;
+ const char *end1 = s1 + n1;
+ const char *end2 = s2 + n2;
/* ignore line endings */
- while ((*last1 == '\r') || (*last1 == '\n'))
- last1--;
- while ((*last2 == '\r') || (*last2 == '\n'))
- last2--;
-
- /* skip leading whitespaces, if both begin with whitespace */
- if (s1 <= last1 && s2 <= last2 && isspace(*s1) && isspace(*s2)) {
- while (isspace(*s1) && (s1 <= last1))
- s1++;
- while (isspace(*s2) && (s2 <= last2))
- s2++;
- }
- /* early return if both lines are empty */
- if ((s1 > last1) && (s2 > last2))
- return 1;
- while (!result) {
- result = *s1++ - *s2++;
- /*
- * Skip whitespace inside. We check for whitespace on
- * both buffers because we don't want "a b" to match
- * "ab"
- */
- if (isspace(*s1) && isspace(*s2)) {
- while (isspace(*s1) && s1 <= last1)
+ while (s1 < end1 && (end1[-1] == '\r' || end1[-1] == '\n'))
+ end1--;
+ while (s2 < end2 && (end2[-1] == '\r' || end2[-1] == '\n'))
+ end2--;
+
+ while (s1 < end1 && s2 < end2) {
+ if (isspace(*s1)) {
+ /*
+ * Skip whitespace. We check on both buffers
+ * because we don't want "a b" to match "ab".
+ */
+ if (!isspace(*s2))
+ return 0;
+ while (s1 < end1 && isspace(*s1))
s1++;
- while (isspace(*s2) && s2 <= last2)
+ while (s2 < end2 && isspace(*s2))
s2++;
- }
- /*
- * If we reached the end on one side only,
- * lines don't match
- */
- if (
- ((s2 > last2) && (s1 <= last1)) ||
- ((s1 > last1) && (s2 <= last2)))
+ } else if (*s1++ != *s2++)
return 0;
- if ((s1 > last1) && (s2 > last2))
- break;
}
- return !result;
+ /* If we reached the end on one side only, lines don't match. */
+ return s1 == end1 && s2 == end2;
}
static void add_line_info(struct image *img, const char *bol, size_t len, unsigned flag)