urlapi: run the urlparser perf test faster
No binary (build failed)
—
(log yok)
| @@ -55,9 +55,6 @@ | |
| #define MAX_SCHEME_LEN 40 | |
| #define MAX_ZONEID_LEN 16 | |
| - | /* characters not allowed in hostnames */ |
| - | #define HOSTNAME_INVALID_CHARS " \r\n\t/:#?!@{}[]\\$\'\"^`*<>=;,+&()%|" |
| - | |
| /* | |
| * If USE_IPV6 is disabled, we still want to parse IPv6 addresses, so make | |
| * sure we have _some_ value for AF_INET6 without polluting our fake value | |
| @@ -148,17 +145,21 @@ UNITTEST CURLUcode urlencode_str(struct dynbuf *o, const char *url, | |
| len -= n; | |
| } | |
| - | for(iptr = host_sep; len && !result; iptr++, len--) { |
| + | for(iptr = host_sep; len && !result;) { |
| if(*iptr == ' ') { | |
| if(query != QUERY_YES) | |
| result = curlx_dyn_addn(o, "%20", 3); | |
| else | |
| result = curlx_dyn_addn(o, "+", 1); | |
| + | iptr++; |
| + | len--; |
| } | |
| else if((*iptr < ' ') || (*iptr >= 0x7f)) { | |
| unsigned char out[3] = { '%' }; | |
| Curl_hexbyte(&out[1], *iptr); | |
| result = curlx_dyn_addn(o, out, 3); | |
| + | iptr++; |
| + | len--; |
| } | |
| else if(*iptr == '%' && (len >= 3) && | |
| ISXDIGIT(iptr[1]) && ISXDIGIT(iptr[2]) && | |
| @@ -169,13 +170,30 @@ UNITTEST CURLUcode urlencode_str(struct dynbuf *o, const char *url, | |
| unsigned char out[3] = { '%' }; | |
| Curl_hexbyte(&out[1], hex); | |
| result = curlx_dyn_addn(o, out, 3); | |
| - | iptr += 2; |
| - | len -= 2; |
| + | iptr += 3; |
| + | len -= 3; |
| } | |
| else { | |
| - | result = curlx_dyn_addn(o, iptr, 1); |
| - | if(*iptr == '?' && (query == QUERY_NOT_YET)) |
| - | query = QUERY_YES; |
| + | const unsigned char *start = iptr; |
| + | while(len) { |
| + | if(*iptr == ' ' || *iptr < ' ' || *iptr >= 0x7f) |
| + | break; |
| + | if(*iptr == '%' && (len >= 3) && |
| + | ISXDIGIT(iptr[1]) && ISXDIGIT(iptr[2]) && |
| + | (ISLOWER(iptr[1]) || ISLOWER(iptr[2]))) |
| + | break; |
| + | if(*iptr == '?') { |
| + | if(query == QUERY_NOT_YET) { |
| + | iptr++; |
| + | len--; |
| + | query = QUERY_YES; |
| + | break; |
| + | } |
| + | } |
| + | iptr++; |
| + | len--; |
| + | } |
| + | result = curlx_dyn_addn(o, (const char *)start, (size_t)(iptr - start)); |
| } | |
| } | |
| @@ -204,18 +222,20 @@ size_t Curl_is_absolute_url(const char *url, char *buf, size_t buflen, | |
| if(guess_scheme && STARTS_WITH_DRIVE_PREFIX(url)) | |
| return 0; | |
| #endif | |
| - | if(ISALPHA(url[0])) |
| + | if(ISALPHA(url[0])) { |
| + | if(buf) |
| + | buf[0] = Curl_raw_tolower(url[0]); |
| for(i = 1; i < MAX_SCHEME_LEN; ++i) { | |
| char s = url[i]; | |
| if(s && (ISALNUM(s) || (s == '+') || (s == '-') || (s == '.'))) { | |
| - | /* RFC 3986 3.1 explains: |
| - | scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) |
| - | */ |
| + | if(buf) |
| + | buf[i] = Curl_raw_tolower(s); |
| } | |
| else { | |
| break; | |
| } | |
| } | |
| + | } |
| if(i && (url[i] == ':') && ((url[i + 1] == '/') || !guess_scheme)) { | |
| /* If this does not guess scheme, the scheme always ends with the colon so | |
| that this also detects data: URLs etc. In guessing mode, data: could | |
| @@ -223,32 +243,26 @@ size_t Curl_is_absolute_url(const char *url, char *buf, size_t buflen, | |
| /* the length of the scheme is the name part only */ | |
| size_t len = i; | |
| - | if(buf) { |
| - | Curl_strntolower(buf, url, i); |
| + | if(buf) |
| buf[i] = 0; | |
| - | } |
| return len; | |
| } | |
| + | if(buf) |
| + | buf[0] = 0; |
| return 0; | |
| } | |
| - | /* scan for byte values <= 31, 127 and sometimes space */ |
| - | CURLUcode Curl_junkscan(const char *url, size_t *urllen, bool allowspace) |
| + | /* scan for byte values <= 31, 127 and maybe space */ |
| + | static bool badoctets(const char *input, size_t n, int flags) |
| { | |
| - | size_t n = strlen(url); |
| - | size_t i; |
| - | unsigned char control; |
| - | const unsigned char *p = (const unsigned char *)url; |
| - | if(n > CURL_MAX_INPUT_LENGTH) |
| - | return CURLUE_MALFORMED_INPUT; |
| - | |
| - | control = allowspace ? 0x1f : 0x20; |
| - | for(i = 0; i < n; i++) { |
| - | if(p[i] <= control || p[i] == 127) |
| - | return CURLUE_MALFORMED_INPUT; |
| + | const uint8_t *p = (const unsigned char *)input; |
| + | const uint8_t control = flags & CURLU_ALLOW_SPACE ? 0x1f : 0x20; |
| + | while(n--) { |
| + | if(*p <= control || *p == 127) |
| + | return TRUE; |
| + | p++; |
| } | |
| - | *urllen = n; |
| - | return CURLUE_OK; |
| + | return FALSE; |
| } | |
| /* | |
| @@ -336,9 +350,20 @@ UNITTEST CURLUcode parse_hostname_login(struct Curl_URL *u, | |
| u->options = optionsp; | |
| } | |
| - | /* the hostname starts at this offset */ |
| - | *hostname_offset = ptr - login; |
| - | return CURLUE_OK; |
| + | if(userp && badoctets(userp, strlen(userp), flags)) |
| + | ures = CURLUE_BAD_USER; |
| + | else if(passwdp && badoctets(passwdp, strlen(passwdp), flags)) |
| + | ures = CURLUE_BAD_PASSWORD; |
| + | else if(optionsp && badoctets(optionsp, strlen(optionsp), flags)) |
| + | ures = CURLUE_MALFORMED_INPUT; |
| + | |
| + | userp = passwdp = optionsp = NULL; |
| + | |
| + | if(!ures) { |
| + | /* the hostname starts at this offset */ |
| + | *hostname_offset = ptr - login; |
| + | return CURLUE_OK; |
| + | } |
| out: | |
| @@ -368,7 +393,7 @@ UNITTEST CURLUcode parse_port(struct Curl_URL *u, struct dynbuf *host, | |
| u->portnum = 0; | |
| u->port_present = FALSE; | |
| if(hostname[0] == '[') { | |
| - | portptr = strchr(hostname, ']'); |
| + | portptr = memchr(hostname + 1, ']', curlx_dyn_len(host) - 1); |
| if(!portptr) | |
| return CURLUE_BAD_IPV6; | |
| portptr++; | |
| @@ -381,7 +406,7 @@ UNITTEST CURLUcode parse_port(struct Curl_URL *u, struct dynbuf *host, | |
| portptr = NULL; | |
| } | |
| else | |
| - | portptr = strchr(hostname, ':'); |
| + | portptr = memchr(hostname, ':', curlx_dyn_len(host)); |
| if(portptr) { | |
| curl_off_t port; | |
| @@ -476,31 +501,50 @@ UNITTEST CURLUcode ipv6_parse(struct Curl_URL *u, char *hostname, | |
| return CURLUE_OK; | |
| } | |
| - | static CURLUcode hostname_check(struct Curl_URL *u, char *hostname, |
| + | /* characters not allowed in hostnames: |
| + | " \r\n\t/:#?!@{}[]\\$\'\"^`*<>=;,+&()%|" */ |
| + | |
| + | static const bool invalid_host_char[256] = { |
| + | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x00-0x0F */ |
| + | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x10-0x1F */ |
| + | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, /* 0x20-0x2F */ |
| + | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* 0x30-0x3F */ |
| + | 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40-0x4F */ |
| + | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, /* 0x50-0x5F */ |
| + | 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x6F */ |
| + | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1 /* 0x70-0x7F */ |
| + | }; |
| + | |
| + | /* the input is a confirmed hostname, never an IPv6 address */ |
| + | static CURLUcode hostname_check(char *hostname, size_t hlen) |
| + | { |
| + | size_t i; |
| + | for(i = 0; i < hlen; i++) { |
| + | if(invalid_host_char[(unsigned char)hostname[i]]) |
| + | return CURLUE_BAD_HOSTNAME; |
| + | } |
| + | if((hlen >= 2) && |
| + | (hostname[hlen - 1] == '.') && (hostname[hlen - 2] == '.')) |
| + | /* more than one trailing dot is not allowed */ |
| + | return CURLUE_BAD_HOSTNAME; |
| + | else if((hlen == 1) && (hostname[0] == '.')) |
| + | /* a single dot alone is not allowed */ |
| + | return CURLUE_BAD_HOSTNAME; |
| + | return CURLUE_OK; |
| + | } |
| + | |
| + | /* the input is a hostname or perhaps an IPv6 address */ |
| + | static CURLUcode hostname_check6(struct Curl_URL *u, char *hostname, |
| size_t hlen) /* length of hostname */ | |
| { | |
| - | size_t len; |
| DEBUGASSERT(hostname); | |
| if(!hlen) | |
| return CURLUE_NO_HOST; | |
| else if(hostname[0] == '[') | |
| return ipv6_parse(u, hostname, hlen); | |
| - | else { |
| - | /* letters from the second string are not ok */ |
| - | len = strcspn(hostname, HOSTNAME_INVALID_CHARS); |
| - | if(hlen != len) |
| - | /* hostname with bad content */ |
| - | return CURLUE_BAD_HOSTNAME; |
| - | else if((hlen >= 2) && |
| - | (hostname[hlen - 1] == '.') && (hostname[hlen - 2] == '.')) |
| - | /* more than one trailing dot is not allowed */ |
| - | return CURLUE_BAD_HOSTNAME; |
| - | else if((hlen == 1) && (hostname[0] == '.')) |
| - | /* a single dot alone is not allowed */ |
| - | return CURLUE_BAD_HOSTNAME; |
| - | } |
| - | return CURLUE_OK; |
| + | |
| + | return hostname_check(hostname, hlen); |
| } | |
| /* | |
| @@ -529,14 +573,14 @@ UNITTEST int ipv4_normalize(struct dynbuf *host) | |
| unsigned int parts[4] = { 0, 0, 0, 0 }; | |
| CURLcode result = CURLE_OK; | |
| - | if(*c == '[') |
| - | return HOST_IPV6; |
| + | if(!ISDIGIT(*c)) |
| + | return HOST_NAME; |
| while(!done) { | |
| int rc; | |
| curl_off_t l; | |
| if(*c == '0') { | |
| - | if(Curl_raw_tolower(c[1]) == 'x') { |
| + | if((c[1] | 0x20) == 'x') { |
| c += 2; /* skip the prefix */ | |
| rc = curlx_str_hex(&c, &l, UINT_MAX); | |
| if(rc) | |
| @@ -631,7 +675,7 @@ static CURLUcode urldecode_host(struct dynbuf *host) | |
| { | |
| const char *per; | |
| const char *hostname = curlx_dyn_ptr(host); | |
| - | per = strchr(hostname, '%'); |
| + | per = memchr(hostname, '%', curlx_dyn_len(host)); |
| if(!per) | |
| /* nothing to decode */ | |
| return CURLUE_OK; | |
| @@ -676,6 +720,7 @@ static CURLUcode parse_authority(struct Curl_URL *u, | |
| return uc; | |
| } | |
| + | /* parse_port() also sets the hostname length correctly */ |
| uc = parse_port(u, host, has_scheme); | |
| if(!curlx_dyn_len(host)) | |
| @@ -684,23 +729,17 @@ static CURLUcode parse_authority(struct Curl_URL *u, | |
| if(!uc) | |
| uc = urldecode_host(host); | |
| if(uc) | |
| - | return uc; |
| - | |
| - | switch(ipv4_normalize(host)) { |
| - | case HOST_IPV4: |
| - | break; |
| - | case HOST_IPV6: |
| + | ; |
| + | else if(auth[offset] == '[') |
| uc = ipv6_parse(u, curlx_dyn_ptr(host), curlx_dyn_len(host)); | |
| - | break; |
| - | case HOST_NAME: |
| - | uc = hostname_check(u, curlx_dyn_ptr(host), curlx_dyn_len(host)); |
| - | break; |
| - | case HOST_ERROR: |
| - | uc = CURLUE_OUT_OF_MEMORY; |
| - | break; |
| - | default: |
| - | uc = CURLUE_BAD_HOSTNAME; /* Bad IPv4 address even */ |
| - | break; |
| + | else { |
| + | /* ipv4_normalize() returns *NAME, *IPV4 or *ERROR */ |
| + | int type = ipv4_normalize(host); |
| + | |
| + | if(type == HOST_NAME) |
| + | uc = hostname_check(curlx_dyn_ptr(host), curlx_dyn_len(host)); |
| + | else if(type == HOST_ERROR) |
| + | uc = CURLUE_OUT_OF_MEMORY; |
| } | |
| return uc; | |
| @@ -756,6 +795,8 @@ static bool needs_dedotdot(const char *p, size_t pn) | |
| /* a single byte path cannot be cleaned up */ | |
| if(pn < 2) | |
| return FALSE; | |
| + | if(!memchr(p, '.', pn) && !memchr(p, '%', pn)) |
| + | return FALSE; |
| while(pn) { | |
| if(is_dot(&p, &pn)) { | |
| /* "./" or dot before end of string */ | |
| @@ -999,7 +1040,8 @@ static CURLUcode parse_scheme(const char *url, CURLU *u, char *schemebuf, | |
| if(schemelen) { | |
| int num_slashes = 0; | |
| const char *p = &url[schemelen + 1]; | |
| - | if(!Curl_get_scheme(schemebuf) && !(flags & CURLU_NON_SUPPORT_SCHEME)) |
| + | if(!Curl_getn_scheme(schemebuf, schemelen) && |
| + | !(flags & CURLU_NON_SUPPORT_SCHEME)) |
| return CURLUE_UNSUPPORTED_SCHEME; | |
| if(!ISSLASH(*p)) | |
| @@ -1090,6 +1132,8 @@ static CURLUcode handle_fragment(CURLU *u, const char *fragment, | |
| u->fragment = curlx_dyn_ptr(&enc); | |
| } | |
| else { | |
| + | if(badoctets(fragment, fraglen, flags)) |
| + | return CURLUE_BAD_FRAGMENT; |
| u->fragment = curlx_memdup0(fragment + 1, fraglen - 1); | |
| if(!u->fragment) | |
| return CURLUE_OUT_OF_MEMORY; | |
| @@ -1114,6 +1158,9 @@ static CURLUcode handle_query(CURLU *u, const char *query, | |
| u->query = curlx_dyn_ptr(&enc); | |
| } | |
| else { | |
| + | if(badoctets(query, qlen, flags)) |
| + | return CURLUE_BAD_QUERY; |
| + | |
| u->query = curlx_memdup0(query + 1, qlen - 1); | |
| if(!u->query) | |
| return CURLUE_OUT_OF_MEMORY; | |
| @@ -1144,6 +1191,9 @@ static CURLUcode handle_path(CURLU *u, const char *path, | |
| } | |
| if(pathlen >= (size_t)(1 + !is_file)) { | |
| + | if(badoctets(path, pathlen, flags)) |
| + | return CURLUE_BAD_PATH; |
| + | |
| /* paths for file:// scheme can be one byte, others need to be two */ | |
| if(!u->path) { | |
| u->path = curlx_memdup0(path, pathlen); | |
| @@ -1183,31 +1233,35 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags) | |
| DEBUGASSERT(url); | |
| - | curlx_dyn_init(&host, CURL_MAX_INPUT_LENGTH); |
| + | urllen = strlen(url); |
| + | if(urllen > CURL_MAX_INPUT_LENGTH) |
| + | return CURLUE_MALFORMED_INPUT; |
| - | ures = Curl_junkscan(url, &urllen, !!(flags & CURLU_ALLOW_SPACE)); |
| - | if(ures) |
| - | goto fail; |
| + | curlx_dyn_init(&host, CURL_MAX_INPUT_LENGTH); |
| schemelen = Curl_is_absolute_url(url, schemebuf, sizeof(schemebuf), | |
| flags & (CURLU_GUESS_SCHEME | | |
| CURLU_DEFAULT_SCHEME)); | |
| /* handle the file: scheme */ | |
| - | if(schemelen && !strcmp(schemebuf, "file")) { |
| + | if(schemelen == 4 && !memcmp(schemebuf, "file", 4)) { |
| is_file = TRUE; | |
| ures = parse_file(url, urllen, u, &path, &pathlen); | |
| } | |
| else { | |
| const char *hostp = NULL; | |
| + | const char *p; |
| size_t hostlen; | |
| ures = parse_scheme(url, u, schemebuf, schemelen, flags, &hostp); | |
| if(ures) | |
| goto fail; | |
| /* find the end of the hostname + port number */ | |
| - | hostlen = strcspn(hostp, "/?#"); |
| - | path = &hostp[hostlen]; |
| + | p = hostp; |
| + | while(*p && *p != '/' && *p != '?' && *p != '#') |
| + | p++; |
| + | hostlen = p - hostp; |
| + | path = p; |
| /* this pathlen also contains the query and the fragment */ | |
| pathlen = urllen - (path - url); | |
| @@ -1227,7 +1281,7 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags) | |
| if(!ures) { | |
| /* The path might at this point contain a fragment and/or a query to | |
| handle */ | |
| - | const char *fragment = strchr(path, '#'); |
| + | const char *fragment = memchr(path, '#', pathlen); |
| if(fragment) { | |
| size_t fraglen = pathlen - (fragment - path); | |
| ures = handle_fragment(u, fragment, fraglen, flags); | |
| @@ -1999,11 +2053,11 @@ static CURLUcode url_sethost(CURLU *u, struct dynbuf *encp, | |
| size_t dlen; | |
| char *decoded = NULL; | |
| CURLcode result = Curl_urldecode(newp, n, &decoded, &dlen, REJECT_CTRL); | |
| - | if(result || hostname_check(u, decoded, dlen)) |
| + | if(result || hostname_check6(u, decoded, dlen)) |
| bad = TRUE; | |
| curlx_free(decoded); | |
| } | |
| - | else if(hostname_check(u, newp, n)) |
| + | else if(hostname_check6(u, newp, n)) |
| bad = TRUE; | |
| if(bad) { | |
| curlx_dyn_free(encp); | |
| @@ -946,6 +946,18 @@ static CURLcode doh_decode_rdata_name(const unsigned char **buf, | |
| return CURLE_OK; | |
| } | |
| + | /* scan for byte values <= 32 or 127 */ |
| + | static CURLcode junkscan(const char *url) |
| + | { |
| + | const unsigned char *p = (const unsigned char *)url; |
| + | while(*p) { |
| + | if(*p <= 0x20 || *p == 127) |
| + | return CURLE_WEIRD_SERVER_REPLY; |
| + | p++; |
| + | } |
| + | return CURLE_OK; |
| + | } |
| + | |
| /* @unittest 1658 */ | |
| UNITTEST CURLcode doh_resp_decode_httpsrr(struct Curl_easy *data, | |
| const unsigned char *cp, size_t len, | |
| @@ -959,7 +971,6 @@ UNITTEST CURLcode doh_resp_decode_httpsrr(struct Curl_easy *data, | |
| struct Curl_https_rrinfo *lhrr = NULL; | |
| char *dnsname = NULL; | |
| CURLcode result = CURLE_OUT_OF_MEMORY; | |
| - | size_t olen; |
| (void)data; | |
| *hrr = NULL; | |
| @@ -974,9 +985,9 @@ UNITTEST CURLcode doh_resp_decode_httpsrr(struct Curl_easy *data, | |
| if(doh_decode_rdata_name(&cp, &len, &dnsname) != CURLE_OK) | |
| goto err; | |
| lhrr->target = dnsname; | |
| - | if(Curl_junkscan(dnsname, &olen, FALSE)) { |
| + | result = junkscan(dnsname); |
| + | if(result) { |
| /* unacceptable hostname content */ | |
| - | result = CURLE_WEIRD_SERVER_REPLY; |
| goto err; | |
| } | |
| while(len >= 4) { | |
| @@ -194,23 +194,27 @@ static const struct testcase get_parts_list[] = { | |
| "https | [11] | [12] | [13] | [::13.1.68.3] | 1234 " | |
| "| / | [16] | [17]", CURLU_DEFAULT_SCHEME, 0, CURLUE_OK}, | |
| { /* query and fragments with control characters */ | |
| - | "http://host/path/?\001#\002", |
| - | "", CURLU_URLENCODE, 0, CURLUE_MALFORMED_INPUT }, |
| + | "http://host/path/?a\001#b\002", |
| + | "http | [11] | [12] | [13] | host | [15] | /path/ | a%01 | b%02", |
| + | CURLU_URLENCODE, 0, CURLUE_OK }, |
| { /* Control code in port number is never okay, even when URL encoding */ | |
| "http://host:\x1f""80/path/", | |
| - | "", CURLU_URLENCODE, 0, CURLUE_MALFORMED_INPUT }, |
| + | "", CURLU_URLENCODE, 0, CURLUE_BAD_PORT_NUMBER }, |
| { /* Control code in scheme never okay, even when URL encoding */ | |
| "http\x1f://host/path/", | |
| - | "", CURLU_URLENCODE, 0, CURLUE_MALFORMED_INPUT }, |
| + | "", CURLU_URLENCODE, 0, CURLUE_BAD_SCHEME }, |
| { /* Control code in separator never okay, even when URL encoding */ | |
| "http:/%1f/host/path/", | |
| "", CURLU_URLENCODE, 0, CURLUE_BAD_HOSTNAME }, | |
| { /* Path with control characters */ | |
| "http://host/path\001with\002ctrl/", | |
| - | "", CURLU_URLENCODE, 0, CURLUE_MALFORMED_INPUT }, |
| + | "http | [11] | [12] | [13] | host | [15] | /path%01with%02ctrl/ | [16] |" |
| + | " [17]", |
| + | CURLU_URLENCODE, 0, CURLUE_OK }, |
| { /* Path with control characters and space! */ | |
| "http://host/path\x7fwith space/", | |
| - | "", CURLU_URLENCODE, 0, CURLUE_MALFORMED_INPUT }, |
| + | "http | [11] | [12] | [13] | host | [15] | /path%7Fwith%20space/ | [16] " |
| + | "| [17]", CURLU_URLENCODE, 0, CURLUE_OK }, |
| { /* Ensure %2f is NOT normalized to / even if path-as-is is NOT set */ | |
| "http://host/path%2f..%2f/", | |
| "http | [11] | [12] | [13] | host | [15] | /path%2f..%2f/ | [16] | [17]", | |
| @@ -281,7 +285,7 @@ static const struct testcase get_parts_list[] = { | |
| "https | [11] | [12] | [13] | curl.se | [15] | / | [16] | %20%20", | |
| CURLU_URLENCODE | CURLU_ALLOW_SPACE, 0, CURLUE_OK }, | |
| { "", "", 0, 0, CURLUE_MALFORMED_INPUT }, | |
| - | { " ", "", 0, 0, CURLUE_MALFORMED_INPUT }, |
| + | { " ", "", 0, 0, CURLUE_BAD_SCHEME }, |
| { "1h://example.net", "", 0, 0, CURLUE_BAD_SCHEME }, | |
| { "..://example.net", "", 0, 0, CURLUE_BAD_SCHEME }, | |
| { "-ht://example.net", "", 0, 0, CURLUE_BAD_SCHEME }, | |
| @@ -413,15 +417,15 @@ static const struct testcase get_parts_list[] = { | |
| #endif | |
| {"https://user:[email protected]/get?this=and#but frag then", "", | |
| - | CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT}, |
| + | CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_FRAGMENT}, |
| {"https://user:[email protected]/get?this=and what", "", | |
| - | CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT}, |
| + | CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_QUERY}, |
| {"https://user:[email protected]/ge t?this=and-what", "", | |
| - | CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT}, |
| + | CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_PATH}, |
| {"https://user:pass [email protected]/get?this=and-what", "", | |
| - | CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT}, |
| + | CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_PASSWORD}, |
| {"https://u ser:[email protected]/get?this=and-what", "", | |
| - | CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT}, |
| + | CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_USER}, |
| {"imap://user:pass;opt ion@server/path", "", | |
| CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT}, | |
| /* no space allowed in scheme */ | |
| @@ -644,9 +648,9 @@ static const struct testcase get_parts_list[] = { | |
| "https | [11] | [12] | [13] | 127abc.com | [15] | / | [16] | [17]", | |
| CURLU_DEFAULT_SCHEME, 0, CURLUE_OK}, | |
| {"https:// example.com?check", "", | |
| - | CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT}, |
| + | CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_HOSTNAME}, |
| {"https://e x a m p l e.com?check", "", | |
| - | CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT}, |
| + | CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_HOSTNAME}, |
| {"https://example.com?check", | |
| "https | [11] | [12] | [13] | example.com | [15] | / | check | [17]", | |
| CURLU_DEFAULT_SCHEME, 0, CURLUE_OK}, | |
| @@ -732,6 +736,10 @@ static const struct urltestcase get_url_list[] = { | |
| {"https://[fe80%3A%3A20c%3A29ff%3Afe9c%3A409b]/", | |
| "https://[fe80::20c:29ff:fe9c:409b]/", 0, 0, CURLUE_OK }, | |
| + | /* URL encoded [brackets] */ |
| + | {"https://%5bfe80%3A%3A20c%3A29ff%3Afe9c%3A409b%5c/", |
| + | "", 0, 0, CURLUE_BAD_HOSTNAME }, |
| + | |
| /* IPvFuture format */ | |
| {"http://[v1.fe80::abcd]/", "", 0, 0, CURLUE_BAD_IPV6}, | |
| @@ -929,7 +937,7 @@ static const struct urltestcase get_url_list[] = { | |
| {"https://\xff.127.0.0.1", "https://%FF.127.0.0.1/", 0, CURLU_URLENCODE, | |
| CURLUE_OK}, | |
| {"https://127.-0.0.1", "https://127.-0.0.1/", 0, 0, CURLUE_OK}, | |
| - | {"https://127.0. 1", "https://127.0.0.1/", 0, 0, CURLUE_MALFORMED_INPUT}, |
| + | {"https://127.0. 1", "https://127.0.0.1/", 0, 0, CURLUE_BAD_HOSTNAME}, |
| {"https://1.2.3.256", "https://1.2.3.256/", 0, 0, CURLUE_OK}, | |
| {"https://1.2.3.256.", "https://1.2.3.256./", 0, 0, CURLUE_OK}, | |
| {"https://1.2.3.4.5", "https://1.2.3.4.5/", 0, 0, CURLUE_OK}, | |
| @@ -1024,14 +1032,18 @@ static const struct urltestcase get_url_list[] = { | |
| CURLU_GUESS_SCHEME, 0, CURLUE_OK}, | |
| {"HTTP://test/", "http://test/", 0, 0, CURLUE_OK}, | |
| {"http://HO0_-st..~./", "http://HO0_-st..~./", 0, 0, CURLUE_OK}, | |
| - | {"http:/@example.com: 123/", "", 0, 0, CURLUE_MALFORMED_INPUT}, |
| - | {"http:/@example.com:123 /", "", 0, 0, CURLUE_MALFORMED_INPUT}, |
| + | {"http:/@example.com: 123/", "", 0, 0, CURLUE_BAD_PORT_NUMBER}, |
| + | {"http:/@example.com:123 /", "", 0, 0, CURLUE_BAD_PORT_NUMBER}, |
| {"http:/@example.com:123a/", "", 0, 0, CURLUE_BAD_PORT_NUMBER}, | |
| - | {"http://host/file\r", "", 0, 0, CURLUE_MALFORMED_INPUT}, |
| - | {"http://host/file\n\x03", "", 0, 0, CURLUE_MALFORMED_INPUT}, |
| + | {"http://host/file\r", "", 0, 0, CURLUE_BAD_PATH}, |
| + | {"http://host/file?\r", "", 0, 0, CURLUE_BAD_QUERY}, |
| + | {"http://host/file?hello#\r", "", 0, 0, CURLUE_BAD_FRAGMENT}, |
| + | {"http://\r:hej@host/file", "", 0, 0, CURLUE_BAD_USER}, |
| + | {"http://hej:\r@host/file", "", 0, 0, CURLUE_BAD_PASSWORD}, |
| + | {"http://host/file\n\x03", "", 0, 0, CURLUE_BAD_PATH}, |
| {"htt\x02://host/file", "", | |
| - | CURLU_NON_SUPPORT_SCHEME, 0, CURLUE_MALFORMED_INPUT}, |
| - | {" http://host/file", "", 0, 0, CURLUE_MALFORMED_INPUT}, |
| + | CURLU_NON_SUPPORT_SCHEME, 0, CURLUE_BAD_SCHEME}, |
| + | {" http://host/file", "", 0, 0, CURLUE_BAD_SCHEME}, |
| /* here the password ends at the semicolon and options is 'word' */ | |
| {"imap://user:pass;word@host/file", | |
| "imap://user:pass;word@host/file", | |