Unverified Commit 52db5486 authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

curl: fix --local-port integer overflow

The tool's local port command line range parser didn't check for integer
overflows and could pass "weird" data to libcurl for this option.
libcurl however, has a strict range check for the values so it rejects
anything outside of the accepted range.

Reported-by: Brian Carpenter
Closes #3242
parent bda4ef41
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -69,8 +69,8 @@ struct OperationConfig {
  char *headerfile;
  char *ftpport;
  char *iface;
  int localport;
  int localportrange;
  long localport;
  long localportrange;
  unsigned short porttouse;
  char *range;
  long low_speed_limit;
+22 −9
Original line number Diff line number Diff line
@@ -935,22 +935,35 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
      case 'r': /* --ftp-method (undocumented at this point) */
        config->ftp_filemethod = ftpfilemethod(config, nextarg);
        break;
      case 's': /* --local-port */
        rc = sscanf(nextarg, "%d - %d",
                    &config->localport,
                    &config->localportrange);
        if(!rc)
      case 's': { /* --local-port */
        char lrange[7];  /* 16bit base 10 is 5 digits, but we allow 6 so that
                            this catches overflows, not just truncates */
        char *p = nextarg;
        while(ISDIGIT(*p))
          p++;
        if(*p) {
          /* if there's anything more than a plain decimal number */
          *p++ = 0;
          rc = sscanf(p, " - %6s", lrange);
        }
        else
          rc = 0;

        err = str2unum(&config->localport, nextarg);
        if(err || (config->localport > 65535))
          return PARAM_BAD_USE;
        if(rc == 1)
        if(!rc)
          config->localportrange = 1; /* default number of ports to try */
        else {
          err = str2unum(&config->localportrange, lrange);
          if(err || (config->localportrange > 65535))
            return PARAM_BAD_USE;
          config->localportrange -= config->localport;
          if(config->localportrange < 1) {
            warnf(global, "bad range input\n");
          if(config->localportrange < 1)
            return PARAM_BAD_USE;
        }
        }
        break;
      }
      case 'u': /* --ftp-alternative-to-user */
        GetStr(&config->ftp_alternative_to_user, nextarg);
        break;
+2 −3
Original line number Diff line number Diff line
@@ -1371,9 +1371,8 @@ static CURLcode operate_do(struct GlobalConfig *global,

        /* curl 7.15.2 */
        if(config->localport) {
          my_setopt(curl, CURLOPT_LOCALPORT, (long)config->localport);
          my_setopt_str(curl, CURLOPT_LOCALPORTRANGE,
                        (long)config->localportrange);
          my_setopt(curl, CURLOPT_LOCALPORT, config->localport);
          my_setopt_str(curl, CURLOPT_LOCALPORTRANGE, config->localportrange);
        }

        /* curl 7.15.5 */