path: root/dir.c
diff options
authorElijah Newren <>2019-09-17 16:34:55 (GMT)
committerJunio C Hamano <>2019-09-17 19:20:35 (GMT)
commita5e916c7453bc022cb86d7f8528952ccda6a81ce (patch)
tree4927aa8477860cbc1a6752cc3672895dcf75b072 /dir.c
parentbbbb6b0b898d0a03175a902524fb3a371fbd5b3f (diff)
dir: fix off-by-one error in match_pathspec_item
For a pathspec like 'foo/bar' comparing against a path named "foo/", namelen will be 4, and match[namelen] will be 'b'. The correct location of the directory separator is namelen-1. However, other callers of match_pathspec_item() such as builtin/grep.c's submodule_path_match() will compare against a path named "foo" instead of "foo/". It might be better to change all the callers to be consistent, as discussed at and but there are many cases to audit, so for now just make sure we handle both cases with and without a trailing slash. The reason the code worked despite this sometimes-off-by-one error was that the subsequent code immediately checked whether the first matchlen characters matched (which they do) and then bailed and return MATCHED_RECURSIVELY anyway since wildmatch doesn't have the ability to check if "name" can be matched as a directory (or prefix) against the pathspec. Signed-off-by: Elijah Newren <> Signed-off-by: Junio C Hamano <>
Diffstat (limited to 'dir.c')
1 files changed, 2 insertions, 1 deletions
diff --git a/dir.c b/dir.c
index a9168be..bf1a747 100644
--- a/dir.c
+++ b/dir.c
@@ -356,8 +356,9 @@ static int match_pathspec_item(const struct index_state *istate,
/* Perform checks to see if "name" is a super set of the pathspec */
if (flags & DO_MATCH_SUBMODULE) {
/* name is a literal prefix of the pathspec */
+ int offset = name[namelen-1] == '/' ? 1 : 0;
if ((namelen < matchlen) &&
- (match[namelen] == '/') &&
+ (match[namelen-offset] == '/') &&
!ps_strncmp(item, match, name, namelen))