mirror of
https://github.com/moparisthebest/curl
synced 2025-01-11 05:58:01 -05:00
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
This commit is contained in:
parent
79c4864a56
commit
d715d2ac89
@ -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
|
.\" * This software is licensed as described in the file COPYING, which
|
||||||
.\" * you should have received as part of this distribution. The terms
|
.\" * 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
|
The host name can use IDNA. The string must then be encoded as your locale
|
||||||
says or UTF-8 (when winidn is used).
|
says or UTF-8 (when winidn is used).
|
||||||
.IP CURLUPART_PORT
|
.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
|
.IP CURLUPART_PATH
|
||||||
If a path is set in the URL without a leading slash, a slash will be inserted
|
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.
|
automatically when this URL is read from the handle.
|
||||||
|
@ -1145,6 +1145,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
|
|||||||
storep = &u->host;
|
storep = &u->host;
|
||||||
break;
|
break;
|
||||||
case CURLUPART_PORT:
|
case CURLUPART_PORT:
|
||||||
|
u->portnum = 0;
|
||||||
storep = &u->port;
|
storep = &u->port;
|
||||||
break;
|
break;
|
||||||
case CURLUPART_PATH:
|
case CURLUPART_PATH:
|
||||||
@ -1188,11 +1189,17 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
|
|||||||
storep = &u->host;
|
storep = &u->host;
|
||||||
break;
|
break;
|
||||||
case CURLUPART_PORT:
|
case CURLUPART_PORT:
|
||||||
|
{
|
||||||
|
char *endp;
|
||||||
urlencode = FALSE; /* never */
|
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))
|
if((port <= 0) || (port > 0xffff))
|
||||||
return CURLUE_BAD_PORT_NUMBER;
|
return CURLUE_BAD_PORT_NUMBER;
|
||||||
|
if(*endp)
|
||||||
|
/* weirdly provided number, not good! */
|
||||||
|
return CURLUE_MALFORMED_INPUT;
|
||||||
storep = &u->port;
|
storep = &u->port;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case CURLUPART_PATH:
|
case CURLUPART_PATH:
|
||||||
urlskipslash = TRUE;
|
urlskipslash = TRUE;
|
||||||
|
@ -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
|
* This software is licensed as described in the file COPYING, which
|
||||||
* you should have received as part of this distribution. The terms
|
* you should have received as part of this distribution. The terms
|
||||||
@ -99,7 +99,8 @@ struct setcase {
|
|||||||
const char *out;
|
const char *out;
|
||||||
unsigned int urlflags;
|
unsigned int urlflags;
|
||||||
unsigned int setflags;
|
unsigned int setflags;
|
||||||
CURLUcode ucode;
|
CURLUcode ucode; /* for the main URL set */
|
||||||
|
CURLUcode pcode; /* for updating parts */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct testcase {
|
struct testcase {
|
||||||
@ -395,91 +396,115 @@ static int checkurl(const char *url, const char *out)
|
|||||||
|
|
||||||
/* !checksrc! disable SPACEBEFORECOMMA 1 */
|
/* !checksrc! disable SPACEBEFORECOMMA 1 */
|
||||||
static struct setcase set_parts_list[] = {
|
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/",
|
{"https://host/",
|
||||||
"path=%4A%4B%4C,",
|
"path=%4A%4B%4C,",
|
||||||
"https://host/%4a%4b%4c",
|
"https://host/%4a%4b%4c",
|
||||||
0, 0, CURLUE_NO_HOST},
|
0, 0, CURLUE_OK, CURLUE_OK},
|
||||||
{"https://host/mooo?q#f",
|
{"https://host/mooo?q#f",
|
||||||
"path=NULL,query=NULL,fragment=NULL,",
|
"path=NULL,query=NULL,fragment=NULL,",
|
||||||
"https://host/",
|
"https://host/",
|
||||||
0, 0, CURLUE_NO_HOST},
|
0, 0, CURLUE_OK, CURLUE_OK},
|
||||||
{"https://user:secret@host/",
|
{"https://user:secret@host/",
|
||||||
"user=NULL,password=NULL,",
|
"user=NULL,password=NULL,",
|
||||||
"https://host/",
|
"https://host/",
|
||||||
0, 0, CURLUE_NO_HOST},
|
0, 0, CURLUE_OK, CURLUE_OK},
|
||||||
{NULL,
|
{NULL,
|
||||||
"scheme=https,user= @:,host=foobar,",
|
"scheme=https,user= @:,host=foobar,",
|
||||||
"https://%20%20%20%40%3a@foobar/",
|
"https://%20%20%20%40%3a@foobar/",
|
||||||
0, CURLU_URLENCODE, CURLUE_OK},
|
0, CURLU_URLENCODE, CURLUE_OK, CURLUE_OK},
|
||||||
{NULL,
|
{NULL,
|
||||||
"scheme=https,host= ,path= ,user= ,password= ,query= ,fragment= ,",
|
"scheme=https,host= ,path= ,user= ,password= ,query= ,fragment= ,",
|
||||||
"https://%20:%20@%20%20/%20?+#%20",
|
"https://%20:%20@%20%20/%20?+#%20",
|
||||||
0, CURLU_URLENCODE, CURLUE_OK},
|
0, CURLU_URLENCODE, CURLUE_OK, CURLUE_OK},
|
||||||
{NULL,
|
{NULL,
|
||||||
"scheme=https,host=foobar,path=/this /path /is /here,",
|
"scheme=https,host=foobar,path=/this /path /is /here,",
|
||||||
"https://foobar/this%20/path%20/is%20/here",
|
"https://foobar/this%20/path%20/is%20/here",
|
||||||
0, CURLU_URLENCODE, CURLUE_OK},
|
0, CURLU_URLENCODE, CURLUE_OK, CURLUE_OK},
|
||||||
{NULL,
|
{NULL,
|
||||||
"scheme=https,host=foobar,path=\xc3\xa4\xc3\xb6\xc3\xbc,",
|
"scheme=https,host=foobar,path=\xc3\xa4\xc3\xb6\xc3\xbc,",
|
||||||
"https://foobar/%c3%a4%c3%b6%c3%bc",
|
"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/",
|
{"imap://user:secret;opt@host/",
|
||||||
"options=updated,scheme=imaps,password=p4ssw0rd,",
|
"options=updated,scheme=imaps,password=p4ssw0rd,",
|
||||||
"imaps://user:p4ssw0rd;updated@host/",
|
"imaps://user:p4ssw0rd;updated@host/",
|
||||||
0, 0, CURLUE_NO_HOST},
|
0, 0, CURLUE_NO_HOST, CURLUE_OK},
|
||||||
{"imap://user:secret;optit@host/",
|
{"imap://user:secret;optit@host/",
|
||||||
"scheme=https,",
|
"scheme=https,",
|
||||||
"https://user:secret@host/",
|
"https://user:secret@host/",
|
||||||
0, 0, CURLUE_NO_HOST},
|
0, 0, CURLUE_NO_HOST, CURLUE_OK},
|
||||||
{"file:///file#anchor",
|
{"file:///file#anchor",
|
||||||
"scheme=https,host=example,",
|
"scheme=https,host=example,",
|
||||||
"https://example/file#anchor",
|
"https://example/file#anchor",
|
||||||
0, 0, CURLUE_NO_HOST},
|
0, 0, CURLUE_NO_HOST, CURLUE_OK},
|
||||||
{NULL, /* start fresh! */
|
{NULL, /* start fresh! */
|
||||||
"scheme=file,host=127.0.0.1,path=/no,user=anonymous,",
|
"scheme=file,host=127.0.0.1,path=/no,user=anonymous,",
|
||||||
"file:///no",
|
"file:///no",
|
||||||
0, 0, CURLUE_OK},
|
0, 0, CURLUE_OK, CURLUE_OK},
|
||||||
{NULL, /* start fresh! */
|
{NULL, /* start fresh! */
|
||||||
"scheme=ftp,host=127.0.0.1,path=/no,user=anonymous,",
|
"scheme=ftp,host=127.0.0.1,path=/no,user=anonymous,",
|
||||||
"ftp://anonymous@127.0.0.1/no",
|
"ftp://anonymous@127.0.0.1/no",
|
||||||
0, 0, CURLUE_OK},
|
0, 0, CURLUE_OK, CURLUE_OK},
|
||||||
{NULL, /* start fresh! */
|
{NULL, /* start fresh! */
|
||||||
"scheme=https,host=example.com,",
|
"scheme=https,host=example.com,",
|
||||||
"https://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",
|
{"http://user:foo@example.com/path?query#frag",
|
||||||
"fragment=changed,",
|
"fragment=changed,",
|
||||||
"http://user:foo@example.com/path?query#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/",
|
{"http://example.com/",
|
||||||
"scheme=foo,", /* not accepted */
|
"scheme=foo,", /* not accepted */
|
||||||
"http://example.com/",
|
"http://example.com/",
|
||||||
0, 0, CURLUE_OK},
|
0, 0, CURLUE_OK, CURLUE_UNSUPPORTED_SCHEME},
|
||||||
{"http://example.com/",
|
{"http://example.com/",
|
||||||
"scheme=https,path=/hello,fragment=snippet,",
|
"scheme=https,path=/hello,fragment=snippet,",
|
||||||
"https://example.com/hello#snippet",
|
"https://example.com/hello#snippet",
|
||||||
0, 0, CURLUE_OK},
|
0, 0, CURLUE_OK, CURLUE_OK},
|
||||||
{"http://example.com:80",
|
{"http://example.com:80",
|
||||||
"user=foo,port=1922,",
|
"user=foo,port=1922,",
|
||||||
"http://foo@example.com:1922/",
|
"http://foo@example.com:1922/",
|
||||||
0, 0, CURLUE_OK},
|
0, 0, CURLUE_OK, CURLUE_OK},
|
||||||
{"http://example.com:80",
|
{"http://example.com:80",
|
||||||
"user=foo,password=bar,",
|
"user=foo,password=bar,",
|
||||||
"http://foo:bar@example.com:80/",
|
"http://foo:bar@example.com:80/",
|
||||||
0, 0, CURLUE_OK},
|
0, 0, CURLUE_OK, CURLUE_OK},
|
||||||
{"http://example.com:80",
|
{"http://example.com:80",
|
||||||
"user=foo,",
|
"user=foo,",
|
||||||
"http://foo@example.com:80/",
|
"http://foo@example.com:80/",
|
||||||
0, 0, CURLUE_OK},
|
0, 0, CURLUE_OK, CURLUE_OK},
|
||||||
{"http://example.com",
|
{"http://example.com",
|
||||||
"host=www.example.com,",
|
"host=www.example.com,",
|
||||||
"http://www.example.com/",
|
"http://www.example.com/",
|
||||||
0, 0, CURLUE_OK},
|
0, 0, CURLUE_OK, CURLUE_OK},
|
||||||
{"http://example.com:80",
|
{"http://example.com:80",
|
||||||
"scheme=ftp,",
|
"scheme=ftp,",
|
||||||
"ftp://example.com:80/",
|
"ftp://example.com:80/",
|
||||||
0, 0, CURLUE_OK},
|
0, 0, CURLUE_OK, CURLUE_OK},
|
||||||
{NULL, NULL, NULL, 0, 0, 0}
|
{NULL, NULL, NULL, 0, 0, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
static CURLUPart part2id(char *part)
|
static CURLUPart part2id(char *part)
|
||||||
@ -507,9 +532,10 @@ static CURLUPart part2id(char *part)
|
|||||||
return 9999; /* bad input => bad output */
|
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;
|
const char *p = cmd;
|
||||||
|
CURLUcode uc;
|
||||||
|
|
||||||
/* make sure the last command ends with a comma too! */
|
/* make sure the last command ends with a comma too! */
|
||||||
while(p) {
|
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);
|
fprintf(stderr, "%s = %s [%d]\n", part, value, (int)what);
|
||||||
#endif
|
#endif
|
||||||
if(!strcmp("NULL", value))
|
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
|
else
|
||||||
curl_url_set(u, what, value, setflags);
|
uc = curl_url_set(u, what, value, setflags);
|
||||||
|
if(uc)
|
||||||
|
return uc;
|
||||||
}
|
}
|
||||||
p = e + 1;
|
p = e + 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
return CURLUE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct redircase set_url_list[] = {
|
static struct redircase set_url_list[] = {
|
||||||
@ -631,7 +661,15 @@ static int set_parts(void)
|
|||||||
else
|
else
|
||||||
rc = CURLUE_OK;
|
rc = CURLUE_OK;
|
||||||
if(!rc) {
|
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);
|
rc = curl_url_get(urlp, CURLUPART_URL, &url, 0);
|
||||||
|
|
||||||
if(rc) {
|
if(rc) {
|
||||||
|
Loading…
Reference in New Issue
Block a user