aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2019-04-11 13:20:15 +0200
committerDaniel Stenberg <daniel@haxx.se>2019-04-13 11:17:30 +0200
commitd715d2ac89abc0fc98ccb220c7f7cc148e747144 (patch)
tree18e0e2e6a8422ca30ac77e47a16118de953503eb
parent79c4864a563824b19044ef98599f0ccdad262e84 (diff)
urlapi: stricter CURLUPART_PORT parsing
Only allow well formed decimal numbers in the input. Document that the number MUST be between 1 and 65535. Add tests to test 1560 to verify the above. Ref: https://github.com/curl/curl/issues/3753 Closes #3762
-rw-r--r--docs/libcurl/curl_url_set.36
-rw-r--r--lib/urlapi.c11
-rw-r--r--tests/libtest/lib1560.c96
3 files changed, 80 insertions, 33 deletions
diff --git a/docs/libcurl/curl_url_set.3 b/docs/libcurl/curl_url_set.3
index 4c8ff9810..4096d8a23 100644
--- a/docs/libcurl/curl_url_set.3
+++ b/docs/libcurl/curl_url_set.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) 1998 - 2019, 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
@@ -63,7 +63,9 @@ Scheme cannot be URL decoded on set.
The host name can use IDNA. The string must then be encoded as your locale
says or UTF-8 (when winidn is used).
.IP CURLUPART_PORT
-Port cannot be URL encoded on set.
+Port cannot be URL encoded on set. The given port number is provided as a
+string and the decimal number must be between 1 and 65535. Anything else will
+return an error.
.IP CURLUPART_PATH
If a path is set in the URL without a leading slash, a slash will be inserted
automatically when this URL is read from the handle.
diff --git a/lib/urlapi.c b/lib/urlapi.c
index 04b04923e..0eb06d24d 100644
--- a/lib/urlapi.c
+++ b/lib/urlapi.c
@@ -1145,6 +1145,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
storep = &u->host;
break;
case CURLUPART_PORT:
+ u->portnum = 0;
storep = &u->port;
break;
case CURLUPART_PATH:
@@ -1188,12 +1189,18 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
storep = &u->host;
break;
case CURLUPART_PORT:
+ {
+ char *endp;
urlencode = FALSE; /* never */
- port = strtol(part, NULL, 10); /* Port number must be decimal */
+ port = strtol(part, &endp, 10); /* Port number must be decimal */
if((port <= 0) || (port > 0xffff))
return CURLUE_BAD_PORT_NUMBER;
+ if(*endp)
+ /* weirdly provided number, not good! */
+ return CURLUE_MALFORMED_INPUT;
storep = &u->port;
- break;
+ }
+ break;
case CURLUPART_PATH:
urlskipslash = TRUE;
storep = &u->path;
diff --git a/tests/libtest/lib1560.c b/tests/libtest/lib1560.c
index c57fe5830..4dcd3e3df 100644
--- a/tests/libtest/lib1560.c
+++ b/tests/libtest/lib1560.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, 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
@@ -99,7 +99,8 @@ struct setcase {
const char *out;
unsigned int urlflags;
unsigned int setflags;
- CURLUcode ucode;
+ CURLUcode ucode; /* for the main URL set */
+ CURLUcode pcode; /* for updating parts */
};
struct testcase {
@@ -395,91 +396,115 @@ static int checkurl(const char *url, const char *out)
/* !checksrc! disable SPACEBEFORECOMMA 1 */
static struct setcase set_parts_list[] = {
+ {"https://host:1234/",
+ "port=NULL,",
+ "https://host/",
+ 0, 0, CURLUE_OK, CURLUE_OK},
+ {"https://host:1234/",
+ "port=\"\",",
+ "https://host:1234/",
+ 0, 0, CURLUE_OK, CURLUE_BAD_PORT_NUMBER},
+ {"https://host:1234/",
+ "port=56 78,",
+ "https://host:1234/",
+ 0, 0, CURLUE_OK, CURLUE_MALFORMED_INPUT},
+ {"https://host:1234/",
+ "port=0,",
+ "https://host:1234/",
+ 0, 0, CURLUE_OK, CURLUE_BAD_PORT_NUMBER},
+ {"https://host:1234/",
+ "port=65535,",
+ "https://host:65535/",
+ 0, 0, CURLUE_OK, CURLUE_OK},
+ {"https://host:1234/",
+ "port=65536,",
+ "https://host:1234/",
+ 0, 0, CURLUE_OK, CURLUE_BAD_PORT_NUMBER},
{"https://host/",
"path=%4A%4B%4C,",
"https://host/%4a%4b%4c",
- 0, 0, CURLUE_NO_HOST},
+ 0, 0, CURLUE_OK, CURLUE_OK},
{"https://host/mooo?q#f",
"path=NULL,query=NULL,fragment=NULL,",
"https://host/",
- 0, 0, CURLUE_NO_HOST},
+ 0, 0, CURLUE_OK, CURLUE_OK},
{"https://user:secret@host/",
"user=NULL,password=NULL,",
"https://host/",
- 0, 0, CURLUE_NO_HOST},
+ 0, 0, CURLUE_OK, CURLUE_OK},
{NULL,
"scheme=https,user= @:,host=foobar,",
"https://%20%20%20%40%3a@foobar/",
- 0, CURLU_URLENCODE, CURLUE_OK},
+ 0, CURLU_URLENCODE, CURLUE_OK, CURLUE_OK},
{NULL,
"scheme=https,host= ,path= ,user= ,password= ,query= ,fragment= ,",
"https://%20:%20@%20%20/%20?+#%20",
- 0, CURLU_URLENCODE, CURLUE_OK},
+ 0, CURLU_URLENCODE, CURLUE_OK, CURLUE_OK},
{NULL,
"scheme=https,host=foobar,path=/this /path /is /here,",
"https://foobar/this%20/path%20/is%20/here",
- 0, CURLU_URLENCODE, CURLUE_OK},
+ 0, CURLU_URLENCODE, CURLUE_OK, CURLUE_OK},
{NULL,
"scheme=https,host=foobar,path=\xc3\xa4\xc3\xb6\xc3\xbc,",
"https://foobar/%c3%a4%c3%b6%c3%bc",
- 0, CURLU_URLENCODE, CURLUE_OK},
+ 0, CURLU_URLENCODE, CURLUE_OK, CURLUE_OK},
{"imap://user:secret;opt@host/",
"options=updated,scheme=imaps,password=p4ssw0rd,",
"imaps://user:p4ssw0rd;updated@host/",
- 0, 0, CURLUE_NO_HOST},
+ 0, 0, CURLUE_NO_HOST, CURLUE_OK},
{"imap://user:secret;optit@host/",
"scheme=https,",
"https://user:secret@host/",
- 0, 0, CURLUE_NO_HOST},
+ 0, 0, CURLUE_NO_HOST, CURLUE_OK},
{"file:///file#anchor",
"scheme=https,host=example,",
"https://example/file#anchor",
- 0, 0, CURLUE_NO_HOST},
+ 0, 0, CURLUE_NO_HOST, CURLUE_OK},
{NULL, /* start fresh! */
"scheme=file,host=127.0.0.1,path=/no,user=anonymous,",
"file:///no",
- 0, 0, CURLUE_OK},
+ 0, 0, CURLUE_OK, CURLUE_OK},
{NULL, /* start fresh! */
"scheme=ftp,host=127.0.0.1,path=/no,user=anonymous,",
"ftp://anonymous@127.0.0.1/no",
- 0, 0, CURLUE_OK},
+ 0, 0, CURLUE_OK, CURLUE_OK},
{NULL, /* start fresh! */
"scheme=https,host=example.com,",
"https://example.com/",
- 0, CURLU_NON_SUPPORT_SCHEME, CURLUE_OK},
+ 0, CURLU_NON_SUPPORT_SCHEME, CURLUE_OK, CURLUE_OK},
{"http://user:foo@example.com/path?query#frag",
"fragment=changed,",
"http://user:foo@example.com/path?query#changed",
- 0, CURLU_NON_SUPPORT_SCHEME, CURLUE_OK},
+ 0, CURLU_NON_SUPPORT_SCHEME, CURLUE_OK, CURLUE_OK},
{"http://example.com/",
"scheme=foo,", /* not accepted */
"http://example.com/",
- 0, 0, CURLUE_OK},
+ 0, 0, CURLUE_OK, CURLUE_UNSUPPORTED_SCHEME},
{"http://example.com/",
"scheme=https,path=/hello,fragment=snippet,",
"https://example.com/hello#snippet",
- 0, 0, CURLUE_OK},
+ 0, 0, CURLUE_OK, CURLUE_OK},
{"http://example.com:80",
"user=foo,port=1922,",
"http://foo@example.com:1922/",
- 0, 0, CURLUE_OK},
+ 0, 0, CURLUE_OK, CURLUE_OK},
{"http://example.com:80",
"user=foo,password=bar,",
"http://foo:bar@example.com:80/",
- 0, 0, CURLUE_OK},
+ 0, 0, CURLUE_OK, CURLUE_OK},
{"http://example.com:80",
"user=foo,",
"http://foo@example.com:80/",
- 0, 0, CURLUE_OK},
+ 0, 0, CURLUE_OK, CURLUE_OK},
{"http://example.com",
"host=www.example.com,",
"http://www.example.com/",
- 0, 0, CURLUE_OK},
+ 0, 0, CURLUE_OK, CURLUE_OK},
{"http://example.com:80",
"scheme=ftp,",
"ftp://example.com:80/",
- 0, 0, CURLUE_OK},
- {NULL, NULL, NULL, 0, 0, 0}
+ 0, 0, CURLUE_OK, CURLUE_OK},
+ {NULL, NULL, NULL, 0, 0, 0, 0}
};
static CURLUPart part2id(char *part)
@@ -507,9 +532,10 @@ static CURLUPart part2id(char *part)
return 9999; /* bad input => bad output */
}
-static void updateurl(CURLU *u, const char *cmd, unsigned int setflags)
+static CURLUcode updateurl(CURLU *u, const char *cmd, unsigned int setflags)
{
const char *p = cmd;
+ CURLUcode uc;
/* make sure the last command ends with a comma too! */
while(p) {
@@ -528,16 +554,20 @@ static void updateurl(CURLU *u, const char *cmd, unsigned int setflags)
fprintf(stderr, "%s = %s [%d]\n", part, value, (int)what);
#endif
if(!strcmp("NULL", value))
- curl_url_set(u, what, NULL, setflags);
+ uc = curl_url_set(u, what, NULL, setflags);
+ else if(!strcmp("\"\"", value))
+ uc = curl_url_set(u, what, "", setflags);
else
- curl_url_set(u, what, value, setflags);
+ uc = curl_url_set(u, what, value, setflags);
+ if(uc)
+ return uc;
}
p = e + 1;
continue;
}
break;
}
-
+ return CURLUE_OK;
}
static struct redircase set_url_list[] = {
@@ -631,7 +661,15 @@ static int set_parts(void)
else
rc = CURLUE_OK;
if(!rc) {
- updateurl(urlp, set_parts_list[i].set, set_parts_list[i].setflags);
+ CURLUcode uc = updateurl(urlp, set_parts_list[i].set,
+ set_parts_list[i].setflags);
+
+ if(uc != set_parts_list[i].pcode) {
+ fprintf(stderr, "updateurl\nin: %s\nreturned %d (expected %d)\n",
+ set_parts_list[i].set, (int)uc, set_parts_list[i].pcode);
+ error++;
+ }
+
rc = curl_url_get(urlp, CURLUPART_URL, &url, 0);
if(rc) {