summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2018-11-05 11:57:29 +0100
committerDaniel Stenberg <daniel@haxx.se>2018-11-07 08:26:28 +0100
commit994d13a105829d6e4f4db452936eaf0144777aa8 (patch)
tree502534060b5477c339629048c6dc4904304c09d7
parent9df8dc101ba03807a3257ba0922fe4dd03c81ed3 (diff)
downloadcurl-bagder/local-port-overflow.tar.gz
curl: fix --local-port integer overflowbagder/local-port-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
-rw-r--r--src/tool_cfgable.h4
-rw-r--r--src/tool_getparam.c31
-rw-r--r--src/tool_operate.c5
3 files changed, 26 insertions, 14 deletions
diff --git a/src/tool_cfgable.h b/src/tool_cfgable.h
index b719fa219..501c96189 100644
--- a/src/tool_cfgable.h
+++ b/src/tool_cfgable.h
@@ -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;
diff --git a/src/tool_getparam.c b/src/tool_getparam.c
index f153a70ac..663c4dd4d 100644
--- a/src/tool_getparam.c
+++ b/src/tool_getparam.c
@@ -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;
diff --git a/src/tool_operate.c b/src/tool_operate.c
index 5a72b6a8c..46ca316f9 100644
--- a/src/tool_operate.c
+++ b/src/tool_operate.c
@@ -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 */