diff options
author | Patrick Monnerat <patrick@monnerat.net> | 2018-02-07 15:01:51 +0100 |
---|---|---|
committer | Patrick Monnerat <patrick@monnerat.net> | 2018-02-07 15:01:51 +0100 |
commit | a0984eae14b2840a470800bb1bfb18bd99dc302b (patch) | |
tree | 1d73afb809a358f9d33f9a70f1e7b48448d4f975 /lib/curl_fnmatch.c | |
parent | ff07089585300739212d0b3dab66b92d21cafb1d (diff) | |
download | curl-a0984eae14b2840a470800bb1bfb18bd99dc302b.tar.gz |
fnmatch: optimize processing of consecutive *s and ?s pattern characters
Reported-By: Daniel Stenberg
Fixes #2291
Closes #2293
Diffstat (limited to 'lib/curl_fnmatch.c')
-rw-r--r-- | lib/curl_fnmatch.c | 31 |
1 files changed, 18 insertions, 13 deletions
diff --git a/lib/curl_fnmatch.c b/lib/curl_fnmatch.c index f303881d3..0179a4f71 100644 --- a/lib/curl_fnmatch.c +++ b/lib/curl_fnmatch.c @@ -256,7 +256,6 @@ static int loop(const unsigned char *pattern, const unsigned char *string, unsigned char *p = (unsigned char *)pattern; unsigned char *s = (unsigned char *)string; unsigned char charset[CURLFNM_CHSET_SIZE] = { 0 }; - int rc = 0; for(;;) { unsigned char *pp; @@ -265,18 +264,24 @@ static int loop(const unsigned char *pattern, const unsigned char *string, case '*': if(!maxstars) return CURL_FNMATCH_NOMATCH; - while(p[1] == '*') /* eliminate multiple stars */ - p++; - if(*s == '\0' && p[1] == '\0') - return CURL_FNMATCH_MATCH; - rc = loop(p + 1, s, maxstars - 1); /* *.txt matches .txt <=> - .txt matches .txt */ - if(rc == CURL_FNMATCH_MATCH) - return CURL_FNMATCH_MATCH; - if(!*s) - return CURL_FNMATCH_NOMATCH; - s++; /* let the star eat up one character */ - break; + /* Regroup consecutive stars and question marks. This can be done because + '*?*?*' can be expressed as '??*'. */ + for(;;) { + if(*++p == '\0') + return CURL_FNMATCH_MATCH; + if(*p == '?') { + if(!*s++) + return CURL_FNMATCH_NOMATCH; + } + else if(*p != '*') + break; + } + /* Skip string characters until we find a match with pattern suffix. */ + for(maxstars--; *s; s++) { + if(loop(p, s, maxstars) == CURL_FNMATCH_MATCH) + return CURL_FNMATCH_MATCH; + } + return CURL_FNMATCH_NOMATCH; case '?': if(!*s) return CURL_FNMATCH_NOMATCH; |