Commit 5c7455fe authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

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
parent 453e7a7a
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -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;
+1 −0
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ typedef enum {
  PARAM_NO_MEM,
  PARAM_NEXT_OPERATION,
  PARAM_NO_PREFIX,
  PARAM_NUMBER_TOO_LARGE,
  PARAM_LAST
} ParameterError;

+2 −0
Original line number Diff line number Diff line
@@ -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";
  }
+27 −8
Original line number Diff line number Diff line
@@ -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;
+2 −3
Original line number Diff line number Diff line
@@ -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);