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 | |
| parent | ff07089585300739212d0b3dab66b92d21cafb1d (diff) | |
fnmatch: optimize processing of consecutive *s and ?s pattern characters
Reported-By: Daniel Stenberg
Fixes #2291
Closes #2293
Diffstat (limited to 'lib')
| -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; | 
