Commit a0984eae authored by Patrick Monnerat's avatar Patrick Monnerat
Browse files

fnmatch: optimize processing of consecutive *s and ?s pattern characters

Reported-By: Daniel Stenberg
Fixes #2291
Closes #2293
parent ff070895
Loading
Loading
Loading
Loading
+18 −13
Original line number Diff line number Diff line
@@ -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)
      /* Regroup consecutive stars and question marks. This can be done because
         '*?*?*' can be expressed as '??*'. */
      for(;;) {
        if(*++p == '\0')
          return CURL_FNMATCH_MATCH;
      if(!*s)
        if(*p == '?') {
          if(!*s++)
            return CURL_FNMATCH_NOMATCH;
      s++; /* let the star eat up one character */
        }
        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;