Skip to content

Commit 0b6e56d

Browse files
committed
dir.c::match_basename(): pay attention to the length of string parameters
The function takes two counted strings (<basename, basenamelen> and <pattern, patternlen>) as parameters, together with prefix (the length of the prefix in pattern that is to be matched literally without globbing against the basename) and EXC_* flags that tells it how to match the pattern against the basename. However, it did not pay attention to the length of these counted strings. Update them to do the following: * When the entire pattern is to be matched literally, the pattern matches the basename only when the lengths of them are the same, and they match up to that length. * When the pattern is "*" followed by a string to be matched literally, make sure that the basenamelen is equal or longer than the "literal" part of the pattern, and the tail of the basename string matches that literal part. * Otherwise, use the new fnmatch_icase_mem helper to make sure we only lookmake sure we use only look at the counted part of the strings. Because these counted strings are full strings most of the time, we check for termination to avoid unnecessary allocation. Signed-off-by: Junio C Hamano <[email protected]> Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent dc09e9e commit 0b6e56d

File tree

1 file changed

+36
-4
lines changed

1 file changed

+36
-4
lines changed

dir.c

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,33 @@ int fnmatch_icase(const char *pattern, const char *string, int flags)
3434
return fnmatch(pattern, string, flags | (ignore_case ? FNM_CASEFOLD : 0));
3535
}
3636

37+
static int fnmatch_icase_mem(const char *pattern, int patternlen,
38+
const char *string, int stringlen,
39+
int flags)
40+
{
41+
int match_status;
42+
struct strbuf pat_buf = STRBUF_INIT;
43+
struct strbuf str_buf = STRBUF_INIT;
44+
const char *use_pat = pattern;
45+
const char *use_str = string;
46+
47+
if (pattern[patternlen]) {
48+
strbuf_add(&pat_buf, pattern, patternlen);
49+
use_pat = pat_buf.buf;
50+
}
51+
if (string[stringlen]) {
52+
strbuf_add(&str_buf, string, stringlen);
53+
use_str = str_buf.buf;
54+
}
55+
56+
match_status = fnmatch_icase(use_pat, use_str, flags);
57+
58+
strbuf_release(&pat_buf);
59+
strbuf_release(&str_buf);
60+
61+
return match_status;
62+
}
63+
3764
static size_t common_prefix_len(const char **pathspec)
3865
{
3966
const char *n, *first;
@@ -537,15 +564,20 @@ int match_basename(const char *basename, int basenamelen,
537564
int flags)
538565
{
539566
if (prefix == patternlen) {
540-
if (!strcmp_icase(pattern, basename))
567+
if (patternlen == basenamelen &&
568+
!strncmp_icase(pattern, basename, basenamelen))
541569
return 1;
542570
} else if (flags & EXC_FLAG_ENDSWITH) {
571+
/* "*literal" matching against "fooliteral" */
543572
if (patternlen - 1 <= basenamelen &&
544-
!strcmp_icase(pattern + 1,
545-
basename + basenamelen - patternlen + 1))
573+
!strncmp_icase(pattern + 1,
574+
basename + basenamelen - (patternlen - 1),
575+
patternlen - 1))
546576
return 1;
547577
} else {
548-
if (fnmatch_icase(pattern, basename, 0) == 0)
578+
if (fnmatch_icase_mem(pattern, patternlen,
579+
basename, basenamelen,
580+
0) == 0)
549581
return 1;
550582
}
551583
return 0;

0 commit comments

Comments
 (0)