Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

urlapi: do the port number extraction without using sscanf() #10541

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
37 changes: 10 additions & 27 deletions lib/urlapi.c
Expand Up @@ -493,35 +493,21 @@ static CURLUcode parse_hostname_login(struct Curl_URL *u,
UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, struct dynbuf *host,
bool has_scheme)
{
char *portptr = NULL;
char endbracket;
int len;
char *portptr;
char *hostname = Curl_dyn_ptr(host);
/*
* Find the end of an IPv6 address, either on the ']' ending bracket or
* a percent-encoded zone index.
*/
if(1 == sscanf(hostname, "[%*45[0123456789abcdefABCDEF:.]%c%n",
&endbracket, &len)) {
if(']' == endbracket)
portptr = &hostname[len];
else if('%' == endbracket) {
int zonelen = len;
if(1 == sscanf(hostname + zonelen, "%*[^]]%c%n", &endbracket, &len)) {
if(']' != endbracket)
return CURLUE_BAD_IPV6;
portptr = &hostname[--zonelen + len + 1];
}
else
return CURLUE_BAD_IPV6;
}
else
if(hostname[0] == '[') {
portptr = strchr(hostname, ']');
if(!portptr)
return CURLUE_BAD_IPV6;

portptr++;
/* this is a RFC2732-style specified IP-address */
if(portptr && *portptr) {
if(*portptr) {
if(*portptr != ':')
return CURLUE_BAD_IPV6;
return CURLUE_BAD_PORT_NUMBER;
}
else
portptr = NULL;
Expand Down Expand Up @@ -585,11 +571,9 @@ static CURLUcode hostname_check(struct Curl_URL *u, char *hostname,
hostname++;
hlen -= 2;

if(hostname[hlen] != ']')
return CURLUE_BAD_IPV6;

/* only valid letters are ok */
/* only valid IPv6 letters are ok */
len = strspn(hostname, l);

if(hlen != len) {
hlen = len;
if(hostname[len] == '%') {
Expand All @@ -603,8 +587,7 @@ static CURLUcode hostname_check(struct Curl_URL *u, char *hostname,
while(*h && (*h != ']') && (i < 15))
zoneid[i++] = *h++;
if(!i || (']' != *h))
/* impossible to reach? */
return CURLUE_MALFORMED_INPUT;
return CURLUE_BAD_IPV6;
zoneid[i] = 0;
u->zoneid = strdup(zoneid);
if(!u->zoneid)
Expand Down
23 changes: 16 additions & 7 deletions tests/libtest/lib1560.c
Expand Up @@ -466,6 +466,12 @@ static const struct testcase get_parts_list[] ={
};

static const struct urltestcase get_url_list[] = {
{"https://[::%25fakeit];80/moo",
"",
0, 0, CURLUE_BAD_PORT_NUMBER},
{"https://[fe80::20c:29ff:fe9c:409b]-80/moo",
"",
0, 0, CURLUE_BAD_PORT_NUMBER},
#ifdef USE_IDN
{"https://räksmörgås.se/path?q#frag",
"https://xn--rksmrgs-5wao1o.se/path?q#frag", 0, CURLU_PUNYCODE, CURLUE_OK},
Expand Down Expand Up @@ -658,11 +664,14 @@ static const struct urltestcase get_url_list[] = {
{NULL, NULL, 0, 0, CURLUE_OK}
};

static int checkurl(const char *url, const char *out)
static int checkurl(const char *org, const char *url, const char *out)
{
if(strcmp(out, url)) {
fprintf(stderr, "Wanted: %s\nGot : %s\n",
out, url);
fprintf(stderr,
"Org: %s\n"
"Wanted: %s\n"
"Got : %s\n",
org, out, url);
return 1;
}
return 0;
Expand Down Expand Up @@ -967,7 +976,7 @@ static int set_url(void)
error++;
}
else {
if(checkurl(url, set_url_list[i].out)) {
if(checkurl(set_url_list[i].in, url, set_url_list[i].out)) {
error++;
}
}
Expand Down Expand Up @@ -1020,7 +1029,7 @@ static int set_parts(void)
__FILE__, __LINE__, (int)rc, curl_url_strerror(rc));
error++;
}
else if(checkurl(url, set_parts_list[i].out)) {
else if(checkurl(set_parts_list[i].in, url, set_parts_list[i].out)) {
error++;
}
}
Expand Down Expand Up @@ -1060,7 +1069,7 @@ static int get_url(void)
error++;
}
else {
if(checkurl(url, get_url_list[i].out)) {
if(checkurl(get_url_list[i].in, url, get_url_list[i].out)) {
error++;
}
}
Expand Down Expand Up @@ -1163,7 +1172,7 @@ static int append(void)
error++;
}
else {
if(checkurl(url, append_list[i].out)) {
if(checkurl(append_list[i].in, url, append_list[i].out)) {
error++;
}
curl_free(url);
Expand Down
19 changes: 14 additions & 5 deletions tests/unit/unit1653.c
Expand Up @@ -92,11 +92,16 @@ UNITTEST_START
u = curl_url();
if(!u)
goto fail;
ipv6port = strdup("[fe80::250:56ff;fea7:da15]:80");
ipv6port = strdup("[fe80::250:56ff;fea7:da15]:808");
if(!ipv6port)
goto fail;
ret = parse_port(u, ipv6port, FALSE);
fail_unless(ret != CURLUE_OK, "parse_port true on error");
fail_unless(ret == CURLUE_OK, "parse_port returned error");
ret = curl_url_get(u, CURLUPART_PORT, &portnum, 0);
fail_unless(ret == CURLUE_OK, "curl_url_get portnum returned error");
fail_unless(portnum && !strcmp(portnum, "808"), "Check portnumber");

curl_free(portnum);
free_and_clear(ipv6port);
curl_url_cleanup(u);

Expand Down Expand Up @@ -180,15 +185,19 @@ UNITTEST_START
free_and_clear(ipv6port);
curl_url_cleanup(u);

/* Incorrect zone index syntax */
/* Incorrect zone index syntax, but the port extractor doesn't care */
u = curl_url();
if(!u)
goto fail;
ipv6port = strdup("[fe80::250:56ff:fea7:da15!25eth3]:80");
ipv6port = strdup("[fe80::250:56ff:fea7:da15!25eth3]:180");
if(!ipv6port)
goto fail;
ret = parse_port(u, ipv6port, FALSE);
fail_unless(ret != CURLUE_OK, "parse_port returned non-error");
fail_unless(ret == CURLUE_OK, "parse_port returned error");
ret = curl_url_get(u, CURLUPART_PORT, &portnum, 0);
fail_unless(ret == CURLUE_OK, "curl_url_get portnum returned error");
fail_unless(portnum && !strcmp(portnum, "180"), "Check portnumber");
curl_free(portnum);
free_and_clear(ipv6port);
curl_url_cleanup(u);

Expand Down