Skip to content

Commit f834089

Browse files
committed
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
2 parents 140b947 + 3dc0b7f commit f834089

File tree

3 files changed

+27
-9
lines changed

3 files changed

+27
-9
lines changed

t/t3070-wildmatch.sh

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,4 +431,15 @@ match 1 1 1 1 'a' '[B-a]'
431431
match 0 1 0 1 'z' '[Z-y]'
432432
match 1 1 1 1 'Z' '[Z-y]'
433433

434+
test_expect_success 'matching does not exhibit exponential behavior' '
435+
{
436+
test-tool wildmatch wildmatch \
437+
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab \
438+
"*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a" &
439+
pid=$!
440+
} &&
441+
sleep 2 &&
442+
! kill $!
443+
'
444+
434445
test_done

wildmatch.c

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@
1414

1515
typedef unsigned char uchar;
1616

17+
/* Internal return values */
18+
#define WM_ABORT_ALL -1
19+
#define WM_ABORT_TO_STARSTAR -2
20+
1721
/* What character marks an inverted character class? */
1822
#define NEGATE_CLASS '!'
1923
#define NEGATE_CLASS2 '^'
@@ -83,12 +87,12 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags)
8387
continue;
8488
case '*':
8589
if (*++p == '*') {
86-
const uchar *prev_p = p - 2;
90+
const uchar *prev_p = p;
8791
while (*++p == '*') {}
8892
if (!(flags & WM_PATHNAME))
8993
/* without WM_PATHNAME, '*' == '**' */
9094
match_slash = 1;
91-
else if ((prev_p < pattern || *prev_p == '/') &&
95+
else if ((prev_p - pattern < 2 || *(prev_p - 2) == '/') &&
9296
(*p == '\0' || *p == '/' ||
9397
(p[0] == '\\' && p[1] == '/'))) {
9498
/*
@@ -114,7 +118,7 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags)
114118
* only if there are no more slash characters. */
115119
if (!match_slash) {
116120
if (strchr((char *)text, '/'))
117-
return WM_NOMATCH;
121+
return WM_ABORT_TO_STARSTAR;
118122
}
119123
return WM_MATCH;
120124
} else if (!match_slash && *p == '/') {
@@ -125,7 +129,7 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags)
125129
*/
126130
const char *slash = strchr((char*)text, '/');
127131
if (!slash)
128-
return WM_NOMATCH;
132+
return WM_ABORT_ALL;
129133
text = (const uchar*)slash;
130134
/* the slash is consumed by the top-level for loop */
131135
break;
@@ -153,8 +157,12 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags)
153157
break;
154158
text++;
155159
}
156-
if (t_ch != p_ch)
157-
return WM_NOMATCH;
160+
if (t_ch != p_ch) {
161+
if (match_slash)
162+
return WM_ABORT_ALL;
163+
else
164+
return WM_ABORT_TO_STARSTAR;
165+
}
158166
}
159167
if ((matched = dowild(p, text, flags)) != WM_NOMATCH) {
160168
if (!match_slash || matched != WM_ABORT_TO_STARSTAR)
@@ -274,5 +282,6 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags)
274282
/* Match the "pattern" against the "text" string. */
275283
int wildmatch(const char *pattern, const char *text, unsigned int flags)
276284
{
277-
return dowild((const uchar*)pattern, (const uchar*)text, flags);
285+
int res = dowild((const uchar*)pattern, (const uchar*)text, flags);
286+
return res == WM_MATCH ? WM_MATCH : WM_NOMATCH;
278287
}

wildmatch.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66

77
#define WM_NOMATCH 1
88
#define WM_MATCH 0
9-
#define WM_ABORT_ALL -1
10-
#define WM_ABORT_TO_STARSTAR -2
119

1210
int wildmatch(const char *pattern, const char *text, unsigned int flags);
1311
#endif

0 commit comments

Comments
 (0)