Skip to content

Commit 4f2d272

Browse files
committed
ignore: don't leak rules into higher directories
A rule "src" in src/.gitignore must only match subdirectories of src/. The current code does not include this context in the match rule and would thus consider this rule to match the top-level src/ directory instead of the intended src/src/. Keep track fo the context in which the rule was defined so we can perform a prefix match.
1 parent 8fce79b commit 4f2d272

File tree

2 files changed

+28
-0
lines changed

2 files changed

+28
-0
lines changed

src/attr_file.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,21 @@ bool git_attr_fnmatch__match(
347347
const char *filename;
348348
int flags = 0;
349349

350+
/*
351+
* If the rule was generated in a subdirectory, we must only
352+
* use it for paths inside that directory. We can thus return
353+
* a non-match if the prefixes don't match.
354+
*/
355+
if (match->containing_dir) {
356+
if (match->flags & GIT_ATTR_FNMATCH_ICASE) {
357+
if (git__strncasecmp(path->path, match->containing_dir, match->containing_dir_length))
358+
return 0;
359+
} else {
360+
if (git__prefixcmp(path->path, match->containing_dir))
361+
return 0;
362+
}
363+
}
364+
350365
if (match->flags & GIT_ATTR_FNMATCH_ICASE)
351366
flags |= FNM_CASEFOLD;
352367
if (match->flags & GIT_ATTR_FNMATCH_LEADINGDIR)
@@ -566,6 +581,17 @@ int git_attr_fnmatch__parse(
566581
/* leave FULLPATH match on, however */
567582
}
568583

584+
if (context) {
585+
char *slash = strchr(context, '/');
586+
size_t len;
587+
if (slash) {
588+
/* include the slash for easier matching */
589+
len = slash - context + 1;
590+
spec->containing_dir = git_pool_strndup(pool, context, len);
591+
spec->containing_dir_length = len;
592+
}
593+
}
594+
569595
if ((spec->flags & GIT_ATTR_FNMATCH_FULLPATH) != 0 &&
570596
context != NULL && git_path_root(pattern) < 0)
571597
{

src/attr_file.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ extern const char *git_attr__unset;
5252
typedef struct {
5353
char *pattern;
5454
size_t length;
55+
char *containing_dir;
56+
size_t containing_dir_length;
5557
unsigned int flags;
5658
} git_attr_fnmatch;
5759

0 commit comments

Comments
 (0)