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
This commit is contained in:
commit
f834089925
@ -431,4 +431,15 @@ match 1 1 1 1 'a' '[B-a]'
|
|||||||
match 0 1 0 1 'z' '[Z-y]'
|
match 0 1 0 1 'z' '[Z-y]'
|
||||||
match 1 1 1 1 'Z' '[Z-y]'
|
match 1 1 1 1 'Z' '[Z-y]'
|
||||||
|
|
||||||
|
test_expect_success 'matching does not exhibit exponential behavior' '
|
||||||
|
{
|
||||||
|
test-tool wildmatch wildmatch \
|
||||||
|
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab \
|
||||||
|
"*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a" &
|
||||||
|
pid=$!
|
||||||
|
} &&
|
||||||
|
sleep 2 &&
|
||||||
|
! kill $!
|
||||||
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
23
wildmatch.c
23
wildmatch.c
@ -14,6 +14,10 @@
|
|||||||
|
|
||||||
typedef unsigned char uchar;
|
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? */
|
/* What character marks an inverted character class? */
|
||||||
#define NEGATE_CLASS '!'
|
#define NEGATE_CLASS '!'
|
||||||
#define NEGATE_CLASS2 '^'
|
#define NEGATE_CLASS2 '^'
|
||||||
@ -83,12 +87,12 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags)
|
|||||||
continue;
|
continue;
|
||||||
case '*':
|
case '*':
|
||||||
if (*++p == '*') {
|
if (*++p == '*') {
|
||||||
const uchar *prev_p = p - 2;
|
const uchar *prev_p = p;
|
||||||
while (*++p == '*') {}
|
while (*++p == '*') {}
|
||||||
if (!(flags & WM_PATHNAME))
|
if (!(flags & WM_PATHNAME))
|
||||||
/* without WM_PATHNAME, '*' == '**' */
|
/* without WM_PATHNAME, '*' == '**' */
|
||||||
match_slash = 1;
|
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 == '/' ||
|
||||||
(p[0] == '\\' && p[1] == '/'))) {
|
(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. */
|
* only if there are no more slash characters. */
|
||||||
if (!match_slash) {
|
if (!match_slash) {
|
||||||
if (strchr((char *)text, '/'))
|
if (strchr((char *)text, '/'))
|
||||||
return WM_NOMATCH;
|
return WM_ABORT_TO_STARSTAR;
|
||||||
}
|
}
|
||||||
return WM_MATCH;
|
return WM_MATCH;
|
||||||
} else if (!match_slash && *p == '/') {
|
} 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, '/');
|
const char *slash = strchr((char*)text, '/');
|
||||||
if (!slash)
|
if (!slash)
|
||||||
return WM_NOMATCH;
|
return WM_ABORT_ALL;
|
||||||
text = (const uchar*)slash;
|
text = (const uchar*)slash;
|
||||||
/* the slash is consumed by the top-level for loop */
|
/* the slash is consumed by the top-level for loop */
|
||||||
break;
|
break;
|
||||||
@ -153,8 +157,12 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags)
|
|||||||
break;
|
break;
|
||||||
text++;
|
text++;
|
||||||
}
|
}
|
||||||
if (t_ch != p_ch)
|
if (t_ch != p_ch) {
|
||||||
return WM_NOMATCH;
|
if (match_slash)
|
||||||
|
return WM_ABORT_ALL;
|
||||||
|
else
|
||||||
|
return WM_ABORT_TO_STARSTAR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ((matched = dowild(p, text, flags)) != WM_NOMATCH) {
|
if ((matched = dowild(p, text, flags)) != WM_NOMATCH) {
|
||||||
if (!match_slash || matched != WM_ABORT_TO_STARSTAR)
|
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. */
|
/* Match the "pattern" against the "text" string. */
|
||||||
int wildmatch(const char *pattern, const char *text, unsigned int flags)
|
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;
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,6 @@
|
|||||||
|
|
||||||
#define WM_NOMATCH 1
|
#define WM_NOMATCH 1
|
||||||
#define WM_MATCH 0
|
#define WM_MATCH 0
|
||||||
#define WM_ABORT_ALL -1
|
|
||||||
#define WM_ABORT_TO_STARSTAR -2
|
|
||||||
|
|
||||||
int wildmatch(const char *pattern, const char *text, unsigned int flags);
|
int wildmatch(const char *pattern, const char *text, unsigned int flags);
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user