Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.kernel.org/pub/scm/git/git.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2023-04-05 00:28:27 +0300
committerJunio C Hamano <gitster@pobox.com>2023-04-05 00:28:27 +0300
commitf834089925e39cdf786f07757308e14b57973542 (patch)
tree20b456de4b8d596f079109127ad3b9ad3011fa8f /wildmatch.c
parent140b9478dad5d19543c1cb4fd293ccec228f1240 (diff)
parent3dc0b7f0dcd10e9b10018e43d248d245b78bf9be (diff)
Merge branch 'pw/wildmatch-fixes'
The wildmatch library code unlearns exponential behaviour it acquired some time ago since it was borrowed from rsync. * pw/wildmatch-fixes: t3070: make chain lint tester happy wildmatch: hide internal return values wildmatch: avoid undefined behavior wildmatch: fix exponential behavior
Diffstat (limited to 'wildmatch.c')
-rw-r--r--wildmatch.c23
1 files changed, 16 insertions, 7 deletions
diff --git a/wildmatch.c b/wildmatch.c
index 42e38e3459..8ea29141bd 100644
--- a/wildmatch.c
+++ b/wildmatch.c
@@ -14,6 +14,10 @@
typedef unsigned char uchar;
+/* Internal return values */
+#define WM_ABORT_ALL -1
+#define WM_ABORT_TO_STARSTAR -2
+
/* What character marks an inverted character class? */
#define NEGATE_CLASS '!'
#define NEGATE_CLASS2 '^'
@@ -83,12 +87,12 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags)
continue;
case '*':
if (*++p == '*') {
- const uchar *prev_p = p - 2;
+ const uchar *prev_p = p;
while (*++p == '*') {}
if (!(flags & WM_PATHNAME))
/* without WM_PATHNAME, '*' == '**' */
match_slash = 1;
- else if ((prev_p < pattern || *prev_p == '/') &&
+ else if ((prev_p - pattern < 2 || *(prev_p - 2) == '/') &&
(*p == '\0' || *p == '/' ||
(p[0] == '\\' && p[1] == '/'))) {
/*
@@ -114,7 +118,7 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags)
* only if there are no more slash characters. */
if (!match_slash) {
if (strchr((char *)text, '/'))
- return WM_NOMATCH;
+ return WM_ABORT_TO_STARSTAR;
}
return WM_MATCH;
} else if (!match_slash && *p == '/') {
@@ -125,7 +129,7 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags)
*/
const char *slash = strchr((char*)text, '/');
if (!slash)
- return WM_NOMATCH;
+ return WM_ABORT_ALL;
text = (const uchar*)slash;
/* the slash is consumed by the top-level for loop */
break;
@@ -153,8 +157,12 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags)
break;
text++;
}
- if (t_ch != p_ch)
- return WM_NOMATCH;
+ if (t_ch != p_ch) {
+ if (match_slash)
+ return WM_ABORT_ALL;
+ else
+ return WM_ABORT_TO_STARSTAR;
+ }
}
if ((matched = dowild(p, text, flags)) != WM_NOMATCH) {
if (!match_slash || matched != WM_ABORT_TO_STARSTAR)
@@ -274,5 +282,6 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags)
/* Match the "pattern" against the "text" string. */
int wildmatch(const char *pattern, const char *text, unsigned int flags)
{
- return dowild((const uchar*)pattern, (const uchar*)text, flags);
+ int res = dowild((const uchar*)pattern, (const uchar*)text, flags);
+ return res == WM_MATCH ? WM_MATCH : WM_NOMATCH;
}