* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at http://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
***************************************************************************/
#include "tool_setup.h"
-#define _MPRINTF_REPLACE /* we want curl-functions instead of native ones */
-#include <curl/mprintf.h>
-
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+#include "tool_cfgable.h"
+#include "tool_doswin.h"
#include "tool_urlglob.h"
#include "tool_vms.h"
pat->content.Set.ptr_s = 0;
pat->globindex = -1;
- pat->content.Set.elements = malloc(sizeof(char*));
+ pat->content.Set.elements = malloc(sizeof(char *));
if(!pat->content.Set.elements)
return GLOBERROR("out of memory", 0, CURLE_OUT_OF_MEMORY);
- pat->content.Set.elements[0] = malloc(len+1);
+ pat->content.Set.elements[0] = malloc(len + 1);
if(!pat->content.Set.elements[0])
return GLOBERROR("out of memory", 0, CURLE_OUT_OF_MEMORY);
static int multiply(unsigned long *amount, long with)
{
unsigned long sum = *amount * with;
+ if(!with) {
+ *amount = 0;
+ return 0;
+ }
if(sum/with != *amount)
return 1; /* didn't fit, bail out */
*amount = sum;
CURLE_URL_MALFORMAT);
/* add 1 to size since it'll be incremented below */
- if(multiply(amount, pat->content.Set.size+1))
+ if(multiply(amount, pat->content.Set.size + 1))
return GLOBERROR("range overflow", 0, CURLE_URL_MALFORMAT);
/* fall-through */
*buf = '\0';
if(pat->content.Set.elements) {
char **new_arr = realloc(pat->content.Set.elements,
- (pat->content.Set.size + 1) * sizeof(char*));
+ (pat->content.Set.size + 1) * sizeof(char *));
if(!new_arr)
return GLOBERROR("out of memory", 0, CURLE_OUT_OF_MEMORY);
pat->content.Set.elements = new_arr;
}
else
- pat->content.Set.elements = malloc(sizeof(char*));
+ pat->content.Set.elements = malloc(sizeof(char *));
if(!pat->content.Set.elements)
return GLOBERROR("out of memory", 0, CURLE_OUT_OF_MEMORY);
/* character range detected */
char min_c;
char max_c;
- int step=1;
+ char end_c;
+ unsigned long 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[3], &endp, 10);
- if(errno || (*endp != ']'))
- step = -1;
- else {
- pattern = endp+1;
- step = (int)lstep;
- if(step > (max_c - min_c))
- step = -1;
+ if(rc == 3) {
+ if(end_c == ':') {
+ char *endp;
+ errno = 0;
+ step = strtoul(&pattern[4], &endp, 10);
+ if(errno || &pattern[4] == endp || *endp != ']')
+ step = 0;
+ else
+ pattern = endp + 1;
}
+ else if(end_c != ']')
+ /* then this is wrong */
+ rc = 0;
+ else
+ /* end_c == ']' */
+ pattern += 4;
}
- else
- pattern += 4;
*posp += (pattern - *patternp);
- if((rc != 2) || (min_c >= max_c) || ((max_c - min_c) > ('z' - 'a')) ||
- (step < 0) )
+ if(rc != 3 || !step || step > (unsigned)INT_MAX ||
+ (min_c == max_c && step != 1) ||
+ (min_c != max_c && (min_c > max_c || step > (unsigned)(max_c - min_c) ||
+ (max_c - min_c) > ('z' - 'a'))))
/* 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 */
- pat->content.CharRange.step = step;
+ pat->content.CharRange.step = (int)step;
pat->content.CharRange.ptr_c = pat->content.CharRange.min_c = min_c;
pat->content.CharRange.max_c = max_c;
- if(multiply(amount, (pat->content.CharRange.max_c -
- pat->content.CharRange.min_c + 1)))
+ if(multiply(amount, ((pat->content.CharRange.max_c -
+ pat->content.CharRange.min_c) /
+ pat->content.CharRange.step + 1)))
return GLOBERROR("range overflow", *posp, CURLE_URL_MALFORMAT);
}
else if(ISDIGIT(*pattern)) {
errno = 0;
min_n = strtoul(pattern, &endp, 10);
if(errno || (endp == pattern))
- endp=NULL;
+ endp = NULL;
else {
if(*endp != '-')
endp = NULL;
else {
- pattern = endp+1;
+ 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;
+ if(errno)
+ /* overflow */
+ endp = NULL;
+ else if(*endp == ':') {
+ pattern = endp + 1;
errno = 0;
step_n = strtoul(pattern, &endp, 10);
if(errno)
else
step_n = 1;
if(endp && (*endp == ']')) {
- pattern= endp+1;
+ pattern = endp + 1;
}
else
endp = NULL;
}
}
+ fail:
*posp += (pattern - *patternp);
- if(!endp || (min_n > max_n) || (step_n > (max_n - min_n)))
+ if(!endp || !step_n ||
+ (min_n == max_n && step_n != 1) ||
+ (min_n != max_n && (min_n > max_n || step_n > (max_n - min_n))))
/* the pattern is not well-formed */
return GLOBERROR("bad range", *posp, CURLE_URL_MALFORMAT);
pat->content.NumRange.max_n = max_n;
pat->content.NumRange.step = step_n;
- if(multiply(amount, (pat->content.NumRange.max_n -
- pat->content.NumRange.min_n + 1)))
+ if(multiply(amount, ((pat->content.NumRange.max_n -
+ pat->content.NumRange.min_n) /
+ pat->content.NumRange.step + 1)))
return GLOBERROR("range overflow", *posp, CURLE_URL_MALFORMAT);
}
else
size_t sublen = 0;
while(*pattern && *pattern != '{') {
if(*pattern == '[') {
- /* Skip over potential IPv6 literals. */
- size_t skip;
- if(peek_ipv6(pattern, &skip)) {
+ /* skip over IPv6 literals and [] */
+ size_t skip = 0;
+ if(!peek_ipv6(pattern, &skip) && (pattern[1] == ']'))
+ skip = 2;
+ if(skip) {
memcpy(buf, pattern, skip);
buf += skip;
pattern += skip;
/* only allow \ to escape known "special letters" */
if(*pattern == '\\' &&
- (*(pattern+1) == '{' || *(pattern+1) == '[' ||
- *(pattern+1) == '}' || *(pattern+1) == ']') ) {
+ (*(pattern + 1) == '{' || *(pattern + 1) == '[' ||
+ *(pattern + 1) == '}' || *(pattern + 1) == ']') ) {
/* escape character, skip '\' */
++pattern;
}
}
- if(++glob->size > GLOB_PATTERN_NUM)
+ if(++glob->size >= GLOB_PATTERN_NUM)
return GLOBERROR("too many globs", pos, CURLE_URL_MALFORMAT);
}
return res;
}
-CURLcode glob_url(URLGlob** glob, char* url, unsigned long *urlnum,
+CURLcode glob_url(URLGlob **glob, char *url, unsigned long *urlnum,
FILE *error)
{
/*
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) {
for(i = 0; carry && (i < glob->size); i++) {
carry = FALSE;
pat = &glob->pattern[glob->size - 1 - i];
- switch (pat->type) {
+ switch(pat->type) {
case UPTSet:
if((pat->content.Set.elements) &&
(++pat->content.Set.ptr_s == pat->content.Set.size)) {
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;
return CURLE_FAILED_INIT;
}
}
- *buf = '\0';
*globbed = strdup(glob->glob_buffer);
if(!*globbed)
unsigned long i;
char *ptr = filename;
unsigned long num = strtoul(&filename[1], &filename, 10);
- URLPattern *pat =NULL;
+ URLPattern *pat = NULL;
if(num < glob->size) {
num--; /* make it zero based */
/* find the correct glob entry */
- for(i=0; i<glob->size; i++) {
+ for(i = 0; i<glob->size; i++) {
if(glob->pattern[i].globindex == (int)num) {
pat = &glob->pattern[i];
break;
}
if(pat) {
- switch (pat->type) {
+ switch(pat->type) {
case UPTSet:
if(pat->content.Set.elements) {
appendthis = pat->content.Set.elements[pat->content.Set.ptr_s];
appendlen = 1;
break;
case UPTNumRange:
- snprintf(numbuf, sizeof(numbuf), "%0*d",
+ snprintf(numbuf, sizeof(numbuf), "%0*lu",
pat->content.NumRange.padlength,
pat->content.NumRange.ptr_n);
appendthis = numbuf;
stringlen += appendlen;
}
target[stringlen]= '\0';
+
+#if defined(MSDOS) || defined(WIN32)
+ {
+ char *sanitized;
+ SANITIZEcode sc = sanitize_file_name(&sanitized, target,
+ (SANITIZE_ALLOW_PATH |
+ SANITIZE_ALLOW_RESERVED));
+ Curl_safefree(target);
+ if(sc)
+ return CURLE_URL_MALFORMAT;
+ target = sanitized;
+ }
+#endif /* MSDOS || WIN32 */
+
*result = target;
return CURLE_OK;
}
-