diff options
author | Daniel Stenberg <daniel@haxx.se> | 2017-08-06 20:10:40 +0200 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2017-08-07 09:38:45 +0200 |
commit | 5c7455fe7691a18e0f6a85ebe26aae861ccc5284 (patch) | |
tree | a9470b75e0d35b584557c9873885ea68a1c54cd5 | |
parent | 453e7a7a03a2cec749abd3878a48e728c515cca7 (diff) |
curl: detect and bail out early on parameter integer overflows
Make the number parser aware of the maximum limit curl accepts for a
value and return an error immediately if larger, instead of running an
integer overflow later.
Fixes #1730
Closes #1736
-rw-r--r-- | src/tool_getparam.c | 7 | ||||
-rw-r--r-- | src/tool_getparam.h | 1 | ||||
-rw-r--r-- | src/tool_helpers.c | 2 | ||||
-rw-r--r-- | src/tool_paramhlp.c | 35 | ||||
-rw-r--r-- | src/tool_paramhlp.h | 5 |
5 files changed, 36 insertions, 14 deletions
diff --git a/src/tool_getparam.c b/src/tool_getparam.c index 089d28574..b7ee519b3 100644 --- a/src/tool_getparam.c +++ b/src/tool_getparam.c @@ -545,7 +545,8 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ GetStr(&config->oauth_bearer, nextarg); break; case 'c': /* connect-timeout */ - err = str2udouble(&config->connecttimeout, nextarg); + err = str2udouble(&config->connecttimeout, nextarg, + LONG_MAX/1000); if(err) return err; break; @@ -1047,7 +1048,7 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ return err; break; case 'R': /* --expect100-timeout */ - err = str2udouble(&config->expect100timeout, nextarg); + err = str2udouble(&config->expect100timeout, nextarg, LONG_MAX/1000); if(err) return err; break; @@ -1713,7 +1714,7 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ break; case 'm': /* specified max time */ - err = str2udouble(&config->timeout, nextarg); + err = str2udouble(&config->timeout, nextarg, LONG_MAX/1000); if(err) return err; break; diff --git a/src/tool_getparam.h b/src/tool_getparam.h index 29e158816..2148e4091 100644 --- a/src/tool_getparam.h +++ b/src/tool_getparam.h @@ -41,6 +41,7 @@ typedef enum { PARAM_NO_MEM, PARAM_NEXT_OPERATION, PARAM_NO_PREFIX, + PARAM_NUMBER_TOO_LARGE, PARAM_LAST } ParameterError; diff --git a/src/tool_helpers.c b/src/tool_helpers.c index 3d2dbe3ac..b3a9516a8 100644 --- a/src/tool_helpers.c +++ b/src/tool_helpers.c @@ -64,6 +64,8 @@ const char *param2text(int res) return "out of memory"; case PARAM_NO_PREFIX: return "the given option can't be reversed with a --no- prefix"; + case PARAM_NUMBER_TOO_LARGE: + return "too large number"; default: return "unknown error"; } diff --git a/src/tool_paramhlp.c b/src/tool_paramhlp.c index ee37931b8..b9dedc989 100644 --- a/src/tool_paramhlp.c +++ b/src/tool_paramhlp.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, 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 @@ -164,7 +164,11 @@ ParameterError str2num(long *val, const char *str) { if(str) { char *endptr; - long num = strtol(str, &endptr, 10); + long num; + errno = 0; + num = strtol(str, &endptr, 10); + if(errno == ERANGE) + return PARAM_NUMBER_TOO_LARGE; if((endptr != str) && (endptr == str + strlen(str))) { *val = num; return PARAM_OK; /* Ok */ @@ -197,16 +201,27 @@ ParameterError str2unum(long *val, const char *str) * Parse the string and write the double in the given address. Return PARAM_OK * on success, otherwise a parameter specific error enum. * + * The 'max' argument is the maximum value allowed, as the numbers are often + * multiplied when later used. + * * Since this function gets called with the 'nextarg' pointer from within the * getparameter a lot, we must check it for NULL before accessing the str * data. */ -ParameterError str2double(double *val, const char *str) +static ParameterError str2double(double *val, const char *str, long max) { if(str) { char *endptr; - double num = strtod(str, &endptr); + double num; + errno = 0; + num = strtod(str, &endptr); + if(errno == ERANGE) + return PARAM_NUMBER_TOO_LARGE; + if((long)num > max) { + /* too large */ + return PARAM_NUMBER_TOO_LARGE; + } if((endptr != str) && (endptr == str + strlen(str))) { *val = num; return PARAM_OK; /* Ok */ @@ -219,14 +234,17 @@ ParameterError str2double(double *val, const char *str) * Parse the string and write the double in the given address. Return PARAM_OK * on success, otherwise a parameter error enum. ONLY ACCEPTS POSITIVE NUMBERS! * + * The 'max' argument is the maximum value allowed, as the numbers are often + * multiplied when later used. + * * Since this function gets called with the 'nextarg' pointer from within the * getparameter a lot, we must check it for NULL before accessing the str * data. */ -ParameterError str2udouble(double *val, const char *str) +ParameterError str2udouble(double *val, const char *str, long max) { - ParameterError result = str2double(val, str); + ParameterError result = str2double(val, str, max); if(result != PARAM_OK) return result; if(*val < 0) @@ -384,11 +402,12 @@ ParameterError str2offset(curl_off_t *val, const char *str) #if(CURL_SIZEOF_CURL_OFF_T > CURL_SIZEOF_LONG) *val = curlx_strtoofft(str, &endptr, 0); if((*val == CURL_OFF_T_MAX || *val == CURL_OFF_T_MIN) && (errno == ERANGE)) - return PARAM_BAD_NUMERIC; + return PARAM_NUMBER_TOO_LARGE; #else + errno = 0; *val = strtol(str, &endptr, 0); if((*val == LONG_MIN || *val == LONG_MAX) && errno == ERANGE) - return PARAM_BAD_NUMERIC; + return PARAM_NUMBER_TOO_LARGE; #endif if((endptr != str) && (endptr == str + strlen(str))) return PARAM_OK; diff --git a/src/tool_paramhlp.h b/src/tool_paramhlp.h index cdfbacf3f..854f52256 100644 --- a/src/tool_paramhlp.h +++ b/src/tool_paramhlp.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * 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 @@ -33,8 +33,7 @@ void cleanarg(char *str); ParameterError str2num(long *val, const char *str); ParameterError str2unum(long *val, const char *str); -ParameterError str2double(double *val, const char *str); -ParameterError str2udouble(double *val, const char *str); +ParameterError str2udouble(double *val, const char *str, long max); long proto2num(struct OperationConfig *config, long *val, const char *str); |