From 6069042fcbf7a555c344fa1f020fac9b72d27aad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Wed, 5 Nov 2014 16:51:39 +0100 Subject: 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. --- src/attr_file.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'src/attr_file.c') diff --git a/src/attr_file.c b/src/attr_file.c index 562075291..e3692cee9 100644 --- a/src/attr_file.c +++ b/src/attr_file.c @@ -347,6 +347,21 @@ bool git_attr_fnmatch__match( const char *filename; int flags = 0; + /* + * If the rule was generated in a subdirectory, we must only + * use it for paths inside that directory. We can thus return + * a non-match if the prefixes don't match. + */ + if (match->containing_dir) { + if (match->flags & GIT_ATTR_FNMATCH_ICASE) { + if (git__strncasecmp(path->path, match->containing_dir, match->containing_dir_length)) + return 0; + } else { + if (git__prefixcmp(path->path, match->containing_dir)) + return 0; + } + } + if (match->flags & GIT_ATTR_FNMATCH_ICASE) flags |= FNM_CASEFOLD; if (match->flags & GIT_ATTR_FNMATCH_LEADINGDIR) @@ -588,6 +603,17 @@ int git_attr_fnmatch__parse( /* leave FULLPATH match on, however */ } + if (context) { + char *slash = strchr(context, '/'); + size_t len; + if (slash) { + /* include the slash for easier matching */ + len = slash - context + 1; + spec->containing_dir = git_pool_strndup(pool, context, len); + spec->containing_dir_length = len; + } + } + if ((spec->flags & GIT_ATTR_FNMATCH_FULLPATH) != 0 && context != NULL && git_path_root(pattern) < 0) { -- cgit v1.2.3