mirror of
https://github.com/curl/curl.git
synced 2026-08-04 22:56:14 +03:00
urlapi: do the port number extraction without using sscanf()
- sscanf() is rather complex and slow, strchr() much simpler - the port number function does not need to fully verify the IPv6 address anyway as it is done later in the hostname_check() function and doing it twice is unnecessary. Closes #10541
This commit is contained in:
parent
72bb489543
commit
8b27799f8c
3 changed files with 40 additions and 39 deletions
37
lib/urlapi.c
37
lib/urlapi.c
|
|
@ -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;
|
||||
|
|
@ -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] == '%') {
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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},
|
||||
|
|
@ -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;
|
||||
|
|
@ -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++;
|
||||
}
|
||||
}
|
||||
|
|
@ -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++;
|
||||
}
|
||||
}
|
||||
|
|
@ -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++;
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue