From 52f3e1d1092c81a4f574c9fc6cb3818b88434c8d Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Mon, 3 Oct 2016 17:27:16 +0200
Subject: [PATCH 1/3] range: prevent negative end number in a glob range
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

CVE-2016-8620

Bug: https://curl.se/docs/adv_20161102F.html
Reported-by: Luật Nguyễn
---
 src/tool_urlglob.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/src/tool_urlglob.c b/src/tool_urlglob.c
index a357b8b..64c75ba 100644
--- a/src/tool_urlglob.c
+++ b/src/tool_urlglob.c
@@ -255,10 +255,16 @@ static CURLcode glob_range(URLGlob *glob, char **patternp,
     else {
       if(*endp != '-')
         endp = NULL;
       else {
         pattern = endp+1;
+        while(*pattern && ISBLANK(*pattern))
+          pattern++;
+        if(!ISDIGIT(*pattern)) {
+          endp = NULL;
+          goto fail;
+        }
         errno = 0;
         max_n = strtoul(pattern, &endp, 10);
         if(errno || (*endp == ':')) {
           pattern = endp+1;
           errno = 0;
@@ -275,10 +281,11 @@ static CURLcode glob_range(URLGlob *glob, char **patternp,
         else
           endp = NULL;
       }
     }
 
+    fail:
     *posp += (pattern - *patternp);
 
     if(!endp || (min_n > max_n) || (step_n > (max_n - min_n)) || !step_n)
       /* the pattern is not well-formed */
       return GLOBERROR("bad range", *posp, CURLE_URL_MALFORMAT);
-- 
2.9.3


From e97ebe97c2b53d3617c1f4082a2aaa4f1b593ef9 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Mon, 3 Oct 2016 18:23:22 +0200
Subject: [PATCH 2/3] glob_next_url: make sure to stay within the given output
 buffer

---
 src/tool_urlglob.c | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/src/tool_urlglob.c b/src/tool_urlglob.c
index 64c75ba..c45a78b 100644
--- a/src/tool_urlglob.c
+++ b/src/tool_urlglob.c
@@ -429,10 +429,11 @@ CURLcode glob_url(URLGlob** glob, char* url, unsigned long *urlnum,
   *glob = NULL;
 
   glob_buffer = malloc(strlen(url) + 1);
   if(!glob_buffer)
     return CURLE_OUT_OF_MEMORY;
+  glob_buffer[0]=0;
 
   glob_expand = calloc(1, sizeof(URLGlob));
   if(!glob_expand) {
     Curl_safefree(glob_buffer);
     return CURLE_OUT_OF_MEMORY;
@@ -546,33 +547,37 @@ CURLcode glob_next_url(char **globbed, URLGlob *glob)
   for(i = 0; i < glob->size; ++i) {
     pat = &glob->pattern[i];
     switch(pat->type) {
     case UPTSet:
       if(pat->content.Set.elements) {
-        len = strlen(pat->content.Set.elements[pat->content.Set.ptr_s]);
         snprintf(buf, buflen, "%s",
                  pat->content.Set.elements[pat->content.Set.ptr_s]);
+        len = strlen(buf);
         buf += len;
         buflen -= len;
       }
       break;
     case UPTCharRange:
-      *buf++ = pat->content.CharRange.ptr_c;
+      if(buflen) {
+        *buf++ = pat->content.CharRange.ptr_c;
+        *buf = '\0';
+        buflen--;
+      }
       break;
     case UPTNumRange:
-      len = snprintf(buf, buflen, "%0*ld",
-                     pat->content.NumRange.padlength,
-                     pat->content.NumRange.ptr_n);
+      snprintf(buf, buflen, "%0*ld",
+               pat->content.NumRange.padlength,
+               pat->content.NumRange.ptr_n);
+      len = strlen(buf);
       buf += len;
       buflen -= len;
       break;
     default:
       printf("internal error: invalid pattern type (%d)\n", (int)pat->type);
       return CURLE_FAILED_INIT;
     }
   }
-  *buf = '\0';
 
   *globbed = strdup(glob->glob_buffer);
   if(!*globbed)
     return CURLE_OUT_OF_MEMORY;
 
-- 
2.9.3


From 9ce377051290c83176f235b526b87904cad6b388 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Tue, 4 Oct 2016 17:25:09 +0200
Subject: [PATCH 3/3] range: reject char globs with missing end like '[L-]'
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

... which previously would lead to out of boundary reads.

Reported-by: Luật Nguyễn
---
 src/tool_urlglob.c | 34 +++++++++++++++++++---------------
 1 file changed, 19 insertions(+), 15 deletions(-)

diff --git a/src/tool_urlglob.c b/src/tool_urlglob.c
index c45a78b..09d21b6 100644
--- a/src/tool_urlglob.c
+++ b/src/tool_urlglob.c
@@ -186,36 +186,40 @@ static CURLcode glob_range(URLGlob *glob, char **patternp,
 
   if(ISALPHA(*pattern)) {
     /* character range detected */
     char min_c;
     char max_c;
+    char end_c;
     int step=1;
 
     pat->type = UPTCharRange;
 
-    rc = sscanf(pattern, "%c-%c", &min_c, &max_c);
+    rc = sscanf(pattern, "%c-%c%c", &min_c, &max_c, &end_c);
 
-    if((rc == 2) && (pattern[3] == ':')) {
-      char *endp;
-      unsigned long lstep;
-      errno = 0;
-      lstep = strtoul(&pattern[4], &endp, 10);
-      if(errno || (*endp != ']'))
-        step = -1;
-      else {
-        pattern = endp+1;
-        step = (int)lstep;
-        if(step > (max_c - min_c))
+    if(rc == 3) {
+      if(end_c == ':') {
+        char *endp;
+        unsigned long lstep;
+        errno = 0;
+        lstep = strtoul(&pattern[4], &endp, 10);
+        if(errno || (*endp != ']'))
           step = -1;
+        else {
+          pattern = endp+1;
+          step = (int)lstep;
+          if(step > (max_c - min_c))
+            step = -1;
+        }
       }
+      else if(end_c != ']')
+        /* then this is wrong */
+        rc = 0;
     }
-    else
-      pattern += 4;
 
     *posp += (pattern - *patternp);
 
-    if((rc != 2) || (min_c >= max_c) || ((max_c - min_c) > ('z' - 'a')) ||
+    if((rc != 3) || (min_c >= max_c) || ((max_c - min_c) > ('z' - 'a')) ||
        (step <= 0) )
       /* the pattern is not well-formed */
       return GLOBERROR("bad range", *posp, CURLE_URL_MALFORMAT);
 
     /* if there was a ":[num]" thing, use that as step or else use 1 */
-- 
2.9.3

