Skip to content

Commit b3b6a39

Browse files
committed
attr_file: account for escaped escapes when searching trailing space
When determining the trailing space length, we need to honor whether spaces are escaped or not. Currently, we do not check whether the escape itself is escaped, though, which might generate an off-by-one in that case as we will simply treat the space as escaped. Fix this by checking whether the backslashes preceding the space are themselves escaped.
1 parent 10ac298 commit b3b6a39

File tree

2 files changed

+32
-3
lines changed

2 files changed

+32
-3
lines changed

src/attr_file.c

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -565,10 +565,22 @@ void git_attr_path__free(git_attr_path *info)
565565
*/
566566
static size_t trailing_space_length(const char *p, size_t len)
567567
{
568-
size_t n;
568+
size_t n, i;
569569
for (n = len; n; n--) {
570-
if ((p[n-1] != ' ' && p[n-1] != '\t') ||
571-
(n > 1 && p[n-2] == '\\'))
570+
if (p[n-1] != ' ' && p[n-1] != '\t')
571+
break;
572+
573+
/*
574+
* Count escape-characters before space. In case where it's an
575+
* even number of escape characters, then the escape char itself
576+
* is escaped and the whitespace is an unescaped whitespace.
577+
* Otherwise, the last escape char is not escaped and the
578+
* whitespace in an escaped whitespace.
579+
*/
580+
i = n;
581+
while (i > 1 && p[i-2] == '\\')
582+
i--;
583+
if ((n - i) % 2)
572584
break;
573585
}
574586
return len - n;

tests/ignore/path.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,3 +521,20 @@ void test_ignore_path__escaped_slash(void)
521521
assert_is_ignored(true, "inter\\mittent");
522522
assert_is_ignored(true, "trailing\\");
523523
}
524+
525+
void test_ignore_path__escaped_space(void)
526+
{
527+
cl_git_rewritefile(
528+
"attr/.gitignore",
529+
"foo\\\\ \n"
530+
"bar\\\\\\ \n");
531+
assert_is_ignored(true, "foo\\");
532+
assert_is_ignored(false, "foo\\ ");
533+
assert_is_ignored(false, "foo\\\\ ");
534+
assert_is_ignored(false, "foo\\\\");
535+
assert_is_ignored(true, "bar\\ ");
536+
assert_is_ignored(false, "bar\\\\");
537+
assert_is_ignored(false, "bar\\\\ ");
538+
assert_is_ignored(false, "bar\\\\\\");
539+
assert_is_ignored(false, "bar\\\\\\ ");
540+
}

0 commit comments

Comments
 (0)