]> granicus.if.org Git - curl/commitdiff
curl: fix --local-port integer overflow
authorDaniel Stenberg <daniel@haxx.se>
Mon, 5 Nov 2018 10:57:29 +0000 (11:57 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Wed, 7 Nov 2018 10:48:17 +0000 (11:48 +0100)
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

src/tool_cfgable.h
src/tool_getparam.c
src/tool_operate.c

index b719fa21916e14dcc53c92b49bcbb930aff70053..501c961891aa2ecd6671b6dea0e5c09336e0cbd8 100644 (file)
@@ -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;
index f153a70ac8dd9c93a4debde7741a1d4160ed2aed..663c4dd4de1dc8437eb9d9825cc5d4d3c2da6e1c 100644 (file)
@@ -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;
index 5a72b6a8c3e3a5357b9688bc4d094e2a5b61e7d9..46ca316f94f4f99c28ba131db8ca5ceef3a83257 100644 (file)
@@ -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 */