From 52f3e1d1092c81a4f574c9fc6cb3818b88434c8d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg 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.haxx.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 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 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