Unverified Commit 2a1b2b4e authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

curl_fnmatch: only allow 5 '*' sections in a single pattern

... to avoid excessive recursive calls. The number 5 is totally
arbitrary and could be modified if someone has a good motivation.
parent cb5accab
Loading
Loading
Loading
Loading
+7 −3
Original line number Diff line number Diff line
@@ -301,7 +301,8 @@ fail:
  return SETCHARSET_FAIL;
}

static int loop(const unsigned char *pattern, const unsigned char *string)
static int loop(const unsigned char *pattern, const unsigned char *string,
                int maxstars)
{
  loop_state state = CURLFNM_LOOP_DEFAULT;
  unsigned char *p = (unsigned char *)pattern;
@@ -313,11 +314,14 @@ static int loop(const unsigned char *pattern, const unsigned char *string)
    switch(state) {
    case CURLFNM_LOOP_DEFAULT:
      if(*p == '*') {
        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); /* *.txt matches .txt <=> .txt matches .txt */
        rc = loop(p + 1, s, maxstars - 1); /* *.txt matches .txt <=>
                                              .txt matches .txt */
        if(rc == CURL_FNMATCH_MATCH)
          return CURL_FNMATCH_MATCH;
        if(*s) /* let the star eat up one character */
@@ -416,5 +420,5 @@ int Curl_fnmatch(void *ptr, const char *pattern, const char *string)
  if(!pattern || !string) {
    return CURL_FNMATCH_FAIL;
  }
  return loop((unsigned char *)pattern, (unsigned char *)string);
  return loop((unsigned char *)pattern, (unsigned char *)string, 5);
}