urlapi: provide more detailed return codes
Previously, the return code CURLUE_MALFORMED_INPUT was used for almost 30 different URL format violations. This made it hard for users to understand why a particular URL was not acceptable. Since the API cannot point out a specific position within the URL for the problem, this now instead introduces a number of additional and more fine-grained error codes to allow the API to return more exactly in what "part" or section of the URL a problem was detected. Also bug-fixes curl_url_get() with CURLUPART_ZONEID, which previously returned CURLUE_OK even if no zoneid existed. Test cases in 1560 have been adjusted and extended. Tests 1538 and 1559 have been updated. Updated libcurl-errors.3 and curl_url_strerror() accordingly. Closes #8049
This commit is contained in:
parent
a5f5687368
commit
4183b8fe9a
@ -20,7 +20,7 @@
|
||||
.\" *
|
||||
.\" **************************************************************************
|
||||
.\"
|
||||
.TH libcurl-errors 3 "1 Jan 2010" "libcurl 7.20.0" "libcurl errors"
|
||||
.TH libcurl-errors 3 "23 Nov 2021" "libcurl 7.81.0" "libcurl errors"
|
||||
.SH NAME
|
||||
libcurl-errors \- error codes in libcurl
|
||||
.SH DESCRIPTION
|
||||
@ -361,6 +361,30 @@ There is no port part in the URL.
|
||||
There is no query part in the URL.
|
||||
.IP "CURLUE_NO_FRAGMENT (17)"
|
||||
There is no fragment part in the URL.
|
||||
.IP "CURLUE_NO_ZONEID (18)"
|
||||
There is no zoneid set in the URL.
|
||||
.IP "CURLUE_BAD_FILE_URL (19)"
|
||||
The file:// URL is invalid.
|
||||
.IP "CURLUE_BAD_FRAGMENT (20)"
|
||||
The fragment part of the URL contained bad or invalid characters.
|
||||
.IP "CURLUE_BAD_HOSTNAME (21)"
|
||||
The hostname contained bad or invalid characters.
|
||||
.IP "CURLUE_BAD_IPV6 (22)"
|
||||
The IPv6 address hostname contained bad or invalid characters.
|
||||
.IP "CURLUE_BAD_LOGIN (23)"
|
||||
The login part of the URL contained bad or invalid characters.
|
||||
.IP "CURLUE_BAD_PASSWORD (24)"
|
||||
The password part of the URL contained bad or invalid characters.
|
||||
.IP "CURLUE_BAD_PATH (25)"
|
||||
The path part of the URL contained bad or invalid characters.
|
||||
.IP "CURLUE_BAD_QUERY (26)"
|
||||
The query part of the URL contained bad or invalid characters.
|
||||
.IP "CURLUE_BAD_SCHEME (27)"
|
||||
The scheme part of the URL contained bad or invalid characters.
|
||||
.IP "CURLUE_BAD_SLASHES (28)"
|
||||
The URL contained an invalid number of slashes.
|
||||
.IP "CURLUE_BAD_USER (29)"
|
||||
The user part of the URL contained bad or invalid characters.
|
||||
.SH "SEE ALSO"
|
||||
.BR curl_easy_strerror "(3), " curl_multi_strerror "(3), "
|
||||
.BR curl_share_strerror "(3), " curl_url_strerror "(3), "
|
||||
|
||||
@ -838,9 +838,20 @@ CURLSSLSET_UNKNOWN_BACKEND 7.56.0
|
||||
CURLSTS_DONE 7.74.0
|
||||
CURLSTS_FAIL 7.74.0
|
||||
CURLSTS_OK 7.74.0
|
||||
CURLUE_BAD_FILE_URL 7.81.0
|
||||
CURLUE_BAD_FRAGMENT 7.81.0
|
||||
CURLUE_BAD_HANDLE 7.62.0
|
||||
CURLUE_BAD_HOSTNAME 7.81.0
|
||||
CURLUE_BAD_IPV6 7.81.0
|
||||
CURLUE_BAD_LOGIN 7.81.0
|
||||
CURLUE_BAD_PARTPOINTER 7.62.0
|
||||
CURLUE_BAD_PASSWORD 7.81.0
|
||||
CURLUE_BAD_PATH 7.81.0
|
||||
CURLUE_BAD_PORT_NUMBER 7.62.0
|
||||
CURLUE_BAD_QUERY 7.81.0
|
||||
CURLUE_BAD_SCHEME 7.81.0
|
||||
CURLUE_BAD_SLASHES 7.81.0
|
||||
CURLUE_BAD_USER 7.81.0
|
||||
CURLUE_MALFORMED_INPUT 7.62.0
|
||||
CURLUE_NO_FRAGMENT 7.62.0
|
||||
CURLUE_NO_HOST 7.62.0
|
||||
@ -850,6 +861,7 @@ CURLUE_NO_PORT 7.62.0
|
||||
CURLUE_NO_QUERY 7.62.0
|
||||
CURLUE_NO_SCHEME 7.62.0
|
||||
CURLUE_NO_USER 7.62.0
|
||||
CURLUE_NO_ZONEID 7.81.0
|
||||
CURLUE_OK 7.62.0
|
||||
CURLUE_OUT_OF_MEMORY 7.62.0
|
||||
CURLUE_UNKNOWN_PART 7.62.0
|
||||
|
||||
@ -48,6 +48,18 @@ typedef enum {
|
||||
CURLUE_NO_PORT, /* 15 */
|
||||
CURLUE_NO_QUERY, /* 16 */
|
||||
CURLUE_NO_FRAGMENT, /* 17 */
|
||||
CURLUE_NO_ZONEID, /* 18 */
|
||||
CURLUE_BAD_FILE_URL, /* 19 */
|
||||
CURLUE_BAD_FRAGMENT, /* 20 */
|
||||
CURLUE_BAD_HOSTNAME, /* 21 */
|
||||
CURLUE_BAD_IPV6, /* 22 */
|
||||
CURLUE_BAD_LOGIN, /* 23 */
|
||||
CURLUE_BAD_PASSWORD, /* 24 */
|
||||
CURLUE_BAD_PATH, /* 25 */
|
||||
CURLUE_BAD_QUERY, /* 26 */
|
||||
CURLUE_BAD_SCHEME, /* 27 */
|
||||
CURLUE_BAD_SLASHES, /* 28 */
|
||||
CURLUE_BAD_USER, /* 29 */
|
||||
CURLUE_LAST
|
||||
} CURLUcode;
|
||||
|
||||
|
||||
@ -468,10 +468,10 @@ curl_url_strerror(CURLUcode error)
|
||||
return "An invalid 'part' argument was passed as argument";
|
||||
|
||||
case CURLUE_MALFORMED_INPUT:
|
||||
return "A malformed input was passed to a URL API function";
|
||||
return "Malformed input to a URL function";
|
||||
|
||||
case CURLUE_BAD_PORT_NUMBER:
|
||||
return "The port number was not a decimal number between 0 and 65535";
|
||||
return "Port number was not a decimal number between 0 and 65535";
|
||||
|
||||
case CURLUE_UNSUPPORTED_SCHEME:
|
||||
return "This libcurl build doesn't support the given URL scheme";
|
||||
@ -489,28 +489,64 @@ curl_url_strerror(CURLUcode error)
|
||||
return "An unknown part ID was passed to a URL API function";
|
||||
|
||||
case CURLUE_NO_SCHEME:
|
||||
return "There is no scheme part in the URL";
|
||||
return "No scheme part in the URL";
|
||||
|
||||
case CURLUE_NO_USER:
|
||||
return "There is no user part in the URL";
|
||||
return "No user part in the URL";
|
||||
|
||||
case CURLUE_NO_PASSWORD:
|
||||
return "There is no password part in the URL";
|
||||
return "No password part in the URL";
|
||||
|
||||
case CURLUE_NO_OPTIONS:
|
||||
return "There is no options part in the URL";
|
||||
return "No options part in the URL";
|
||||
|
||||
case CURLUE_NO_HOST:
|
||||
return "There is no host part in the URL";
|
||||
return "No host part in the URL";
|
||||
|
||||
case CURLUE_NO_PORT:
|
||||
return "There is no port part in the URL";
|
||||
return "No port part in the URL";
|
||||
|
||||
case CURLUE_NO_QUERY:
|
||||
return "There is no query part in the URL";
|
||||
return "No query part in the URL";
|
||||
|
||||
case CURLUE_NO_FRAGMENT:
|
||||
return "There is no fragment part in the URL";
|
||||
return "No fragment part in the URL";
|
||||
|
||||
case CURLUE_NO_ZONEID:
|
||||
return "No zoneid part in the URL";
|
||||
|
||||
case CURLUE_BAD_LOGIN:
|
||||
return "Bad login part";
|
||||
|
||||
case CURLUE_BAD_IPV6:
|
||||
return "Bad IPv6 address";
|
||||
|
||||
case CURLUE_BAD_HOSTNAME:
|
||||
return "Bad hostname";
|
||||
|
||||
case CURLUE_BAD_FILE_URL:
|
||||
return "Bad file:// URL";
|
||||
|
||||
case CURLUE_BAD_SLASHES:
|
||||
return "Unsupported number of slashes";
|
||||
|
||||
case CURLUE_BAD_SCHEME:
|
||||
return "Bad scheme";
|
||||
|
||||
case CURLUE_BAD_PATH:
|
||||
return "Bad path";
|
||||
|
||||
case CURLUE_BAD_FRAGMENT:
|
||||
return "Bad fragment";
|
||||
|
||||
case CURLUE_BAD_QUERY:
|
||||
return "Bad query";
|
||||
|
||||
case CURLUE_BAD_PASSWORD:
|
||||
return "Bad password";
|
||||
|
||||
case CURLUE_BAD_USER:
|
||||
return "Bad user";
|
||||
|
||||
case CURLUE_LAST:
|
||||
break;
|
||||
|
||||
136
lib/urlapi.c
136
lib/urlapi.c
@ -428,6 +428,29 @@ static char *concat_url(const char *base, const char *relurl)
|
||||
return newest;
|
||||
}
|
||||
|
||||
/* scan for byte values < 31 or 127 */
|
||||
static bool junkscan(const char *part, unsigned int flags)
|
||||
{
|
||||
if(part) {
|
||||
static const char badbytes[]={
|
||||
/* */ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
||||
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||
0x7f, 0x00 /* null-terminate */
|
||||
};
|
||||
size_t n = strlen(part);
|
||||
size_t nfine = strcspn(part, badbytes);
|
||||
if(nfine != n)
|
||||
/* since we don't know which part is scanned, return a generic error
|
||||
code */
|
||||
return TRUE;
|
||||
if(!(flags & CURLU_ALLOW_SPACE) && strchr(part, ' '))
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* parse_hostname_login()
|
||||
*
|
||||
@ -475,7 +498,7 @@ static CURLUcode parse_hostname_login(struct Curl_URL *u,
|
||||
(h && (h->flags & PROTOPT_URLOPTIONS)) ?
|
||||
&optionsp:NULL);
|
||||
if(ccode) {
|
||||
result = CURLUE_MALFORMED_INPUT;
|
||||
result = CURLUE_BAD_LOGIN;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -485,15 +508,28 @@ static CURLUcode parse_hostname_login(struct Curl_URL *u,
|
||||
result = CURLUE_USER_NOT_ALLOWED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(junkscan(userp, flags)) {
|
||||
result = CURLUE_BAD_USER;
|
||||
goto out;
|
||||
}
|
||||
u->user = userp;
|
||||
}
|
||||
|
||||
if(passwdp)
|
||||
if(passwdp) {
|
||||
if(junkscan(passwdp, flags)) {
|
||||
result = CURLUE_BAD_PASSWORD;
|
||||
goto out;
|
||||
}
|
||||
u->password = passwdp;
|
||||
}
|
||||
|
||||
if(optionsp)
|
||||
if(optionsp) {
|
||||
if(junkscan(optionsp, flags)) {
|
||||
result = CURLUE_BAD_LOGIN;
|
||||
goto out;
|
||||
}
|
||||
u->options = optionsp;
|
||||
}
|
||||
|
||||
return CURLUE_OK;
|
||||
out:
|
||||
@ -501,6 +537,9 @@ static CURLUcode parse_hostname_login(struct Curl_URL *u,
|
||||
free(userp);
|
||||
free(passwdp);
|
||||
free(optionsp);
|
||||
u->user = NULL;
|
||||
u->password = NULL;
|
||||
u->options = NULL;
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -524,19 +563,19 @@ UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, char *hostname,
|
||||
int zonelen = len;
|
||||
if(1 == sscanf(hostname + zonelen, "%*[^]]%c%n", &endbracket, &len)) {
|
||||
if(']' != endbracket)
|
||||
return CURLUE_MALFORMED_INPUT;
|
||||
return CURLUE_BAD_IPV6;
|
||||
portptr = &hostname[--zonelen + len + 1];
|
||||
}
|
||||
else
|
||||
return CURLUE_MALFORMED_INPUT;
|
||||
return CURLUE_BAD_IPV6;
|
||||
}
|
||||
else
|
||||
return CURLUE_MALFORMED_INPUT;
|
||||
return CURLUE_BAD_IPV6;
|
||||
|
||||
/* this is a RFC2732-style specified IP-address */
|
||||
if(portptr && *portptr) {
|
||||
if(*portptr != ':')
|
||||
return CURLUE_MALFORMED_INPUT;
|
||||
return CURLUE_BAD_IPV6;
|
||||
}
|
||||
else
|
||||
portptr = NULL;
|
||||
@ -587,29 +626,6 @@ UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, char *hostname,
|
||||
return CURLUE_OK;
|
||||
}
|
||||
|
||||
/* scan for byte values < 31 or 127 */
|
||||
static bool junkscan(const char *part, unsigned int flags)
|
||||
{
|
||||
if(part) {
|
||||
static const char badbytes[]={
|
||||
/* */ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
||||
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||
0x7f, 0x00 /* null-terminate */
|
||||
};
|
||||
size_t n = strlen(part);
|
||||
size_t nfine = strcspn(part, badbytes);
|
||||
if(nfine != n)
|
||||
/* since we don't know which part is scanned, return a generic error
|
||||
code */
|
||||
return TRUE;
|
||||
if(!(flags & CURLU_ALLOW_SPACE) && strchr(part, ' '))
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static CURLUcode hostname_check(struct Curl_URL *u, char *hostname)
|
||||
{
|
||||
size_t len;
|
||||
@ -621,12 +637,12 @@ static CURLUcode hostname_check(struct Curl_URL *u, char *hostname)
|
||||
#endif
|
||||
const char *l = "0123456789abcdefABCDEF:.";
|
||||
if(hlen < 4) /* '[::]' is the shortest possible valid string */
|
||||
return CURLUE_MALFORMED_INPUT;
|
||||
return CURLUE_BAD_IPV6;
|
||||
hostname++;
|
||||
hlen -= 2;
|
||||
|
||||
if(hostname[hlen] != ']')
|
||||
return CURLUE_MALFORMED_INPUT;
|
||||
return CURLUE_BAD_IPV6;
|
||||
|
||||
/* only valid letters are ok */
|
||||
len = strspn(hostname, l);
|
||||
@ -643,6 +659,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;
|
||||
zoneid[i] = 0;
|
||||
u->zoneid = strdup(zoneid);
|
||||
@ -652,13 +669,13 @@ static CURLUcode hostname_check(struct Curl_URL *u, char *hostname)
|
||||
hostname[len + 1] = 0; /* terminate the hostname */
|
||||
}
|
||||
else
|
||||
return CURLUE_MALFORMED_INPUT;
|
||||
return CURLUE_BAD_IPV6;
|
||||
/* hostname is fine */
|
||||
}
|
||||
#ifdef ENABLE_IPV6
|
||||
hostname[hlen] = 0; /* end the address there */
|
||||
if(1 != Curl_inet_pton(AF_INET6, hostname, dest))
|
||||
return CURLUE_MALFORMED_INPUT;
|
||||
return CURLUE_BAD_IPV6;
|
||||
hostname[hlen] = ']'; /* restore ending bracket */
|
||||
#endif
|
||||
}
|
||||
@ -667,7 +684,7 @@ static CURLUcode hostname_check(struct Curl_URL *u, char *hostname)
|
||||
len = strcspn(hostname, " \r\n");
|
||||
if(hlen != len)
|
||||
/* hostname with bad content */
|
||||
return CURLUE_MALFORMED_INPUT;
|
||||
return CURLUE_BAD_HOSTNAME;
|
||||
}
|
||||
if(!hostname[0])
|
||||
return CURLUE_NO_HOST;
|
||||
@ -782,7 +799,7 @@ static CURLUcode decode_host(char *hostname, char **outp)
|
||||
CURLcode result = Curl_urldecode(NULL, hostname, 0,
|
||||
outp, &dlen, REJECT_CTRL);
|
||||
if(result)
|
||||
return CURLUE_MALFORMED_INPUT;
|
||||
return CURLUE_BAD_HOSTNAME;
|
||||
}
|
||||
|
||||
return CURLUE_OK;
|
||||
@ -830,7 +847,7 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
|
||||
if(url_has_scheme && !strcmp(schemebuf, "file")) {
|
||||
if(urllen <= 6)
|
||||
/* file:/ is not enough to actually be a complete file: URL */
|
||||
return CURLUE_MALFORMED_INPUT;
|
||||
return CURLUE_BAD_FILE_URL;
|
||||
|
||||
/* path has been allocated large enough to hold this */
|
||||
strcpy(path, &url[5]);
|
||||
@ -884,7 +901,7 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
|
||||
host name */
|
||||
path = strpbrk(ptr, "/\\:*?\"<>|");
|
||||
if(!path || *path != '/')
|
||||
return CURLUE_MALFORMED_INPUT;
|
||||
return CURLUE_BAD_FILE_URL;
|
||||
|
||||
len = path - ptr;
|
||||
if(len) {
|
||||
@ -897,7 +914,7 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
|
||||
#else
|
||||
/* Invalid file://hostname/, expected localhost or 127.0.0.1 or
|
||||
none */
|
||||
return CURLUE_MALFORMED_INPUT;
|
||||
return CURLUE_BAD_FILE_URL;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@ -914,7 +931,7 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
|
||||
if(('/' == path[0] && STARTS_WITH_URL_DRIVE_PREFIX(&path[1])) ||
|
||||
STARTS_WITH_URL_DRIVE_PREFIX(path)) {
|
||||
/* File drive letters are only accepted in MSDOS/Windows */
|
||||
return CURLUE_MALFORMED_INPUT;
|
||||
return CURLUE_BAD_FILE_URL;
|
||||
}
|
||||
#else
|
||||
/* If the path starts with a slash and a drive letter, ditch the slash */
|
||||
@ -941,7 +958,7 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
|
||||
}
|
||||
if((i < 1) || (i>3))
|
||||
/* less than one or more than three slashes */
|
||||
return CURLUE_MALFORMED_INPUT;
|
||||
return CURLUE_BAD_SLASHES;
|
||||
|
||||
schemep = schemebuf;
|
||||
if(!Curl_builtin_scheme(schemep) &&
|
||||
@ -949,13 +966,13 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
|
||||
return CURLUE_UNSUPPORTED_SCHEME;
|
||||
|
||||
if(junkscan(schemep, flags))
|
||||
return CURLUE_MALFORMED_INPUT;
|
||||
return CURLUE_BAD_SCHEME;
|
||||
}
|
||||
else {
|
||||
/* no scheme! */
|
||||
|
||||
if(!(flags & (CURLU_DEFAULT_SCHEME|CURLU_GUESS_SCHEME)))
|
||||
return CURLUE_MALFORMED_INPUT;
|
||||
return CURLUE_BAD_SCHEME;
|
||||
if(flags & CURLU_DEFAULT_SCHEME)
|
||||
schemep = DEFAULT_SCHEME;
|
||||
|
||||
@ -966,7 +983,8 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
|
||||
}
|
||||
hostp = p; /* host name starts here */
|
||||
|
||||
while(*p && !HOSTNAME_END(*p)) /* find end of host name */
|
||||
/* find the end of the host name + port number */
|
||||
while(*p && !HOSTNAME_END(*p))
|
||||
p++;
|
||||
|
||||
len = p - hostp;
|
||||
@ -976,7 +994,7 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
|
||||
}
|
||||
else {
|
||||
if(!(flags & CURLU_NO_AUTHORITY))
|
||||
return CURLUE_MALFORMED_INPUT;
|
||||
return CURLUE_NO_HOST;
|
||||
}
|
||||
|
||||
len = strlen(p);
|
||||
@ -990,9 +1008,6 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
|
||||
}
|
||||
}
|
||||
|
||||
if(junkscan(path, flags))
|
||||
return CURLUE_MALFORMED_INPUT;
|
||||
|
||||
if((flags & CURLU_URLENCODE) && path[0]) {
|
||||
/* worst case output length is 3x the original! */
|
||||
char *newp = malloc(strlen(path) * 3);
|
||||
@ -1006,6 +1021,8 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
|
||||
fragment = strchr(path, '#');
|
||||
if(fragment) {
|
||||
*fragment++ = 0;
|
||||
if(junkscan(fragment, flags))
|
||||
return CURLUE_BAD_FRAGMENT;
|
||||
if(fragment[0]) {
|
||||
u->fragment = strdup(fragment);
|
||||
if(!u->fragment)
|
||||
@ -1016,12 +1033,17 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
|
||||
query = strchr(path, '?');
|
||||
if(query) {
|
||||
*query++ = 0;
|
||||
if(junkscan(query, flags))
|
||||
return CURLUE_BAD_QUERY;
|
||||
/* done even if the query part is a blank string */
|
||||
u->query = strdup(query);
|
||||
if(!u->query)
|
||||
return CURLUE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if(junkscan(path, flags))
|
||||
return CURLUE_BAD_PATH;
|
||||
|
||||
if(!path[0])
|
||||
/* if there's no path left set, unset */
|
||||
path = NULL;
|
||||
@ -1051,12 +1073,10 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
|
||||
|
||||
if(hostname) {
|
||||
char normalized_ipv4[sizeof("255.255.255.255") + 1];
|
||||
|
||||
/*
|
||||
* Parse the login details and strip them out of the host name.
|
||||
*/
|
||||
if(junkscan(hostname, flags))
|
||||
return CURLUE_MALFORMED_INPUT;
|
||||
|
||||
result = parse_hostname_login(u, &hostname, flags);
|
||||
if(result)
|
||||
return result;
|
||||
@ -1065,6 +1085,9 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
if(junkscan(hostname, flags))
|
||||
return CURLUE_BAD_HOSTNAME;
|
||||
|
||||
if(0 == strlen(hostname) && (flags & CURLU_NO_AUTHORITY)) {
|
||||
/* Skip hostname check, it's allowed to be empty. */
|
||||
u->host = strdup("");
|
||||
@ -1210,6 +1233,7 @@ CURLUcode curl_url_get(CURLU *u, CURLUPart what,
|
||||
break;
|
||||
case CURLUPART_ZONEID:
|
||||
ptr = u->zoneid;
|
||||
ifmissing = CURLUE_NO_ZONEID;
|
||||
break;
|
||||
case CURLUPART_PORT:
|
||||
ptr = u->port;
|
||||
@ -1467,7 +1491,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
|
||||
case CURLUPART_SCHEME:
|
||||
if(strlen(part) > MAX_SCHEME_LEN)
|
||||
/* too long */
|
||||
return CURLUE_MALFORMED_INPUT;
|
||||
return CURLUE_BAD_SCHEME;
|
||||
if(!(flags & CURLU_NON_SUPPORT_SCHEME) &&
|
||||
/* verify that it is a fine scheme */
|
||||
!Curl_builtin_scheme(part))
|
||||
@ -1488,7 +1512,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
|
||||
size_t len = strcspn(part, " \r\n");
|
||||
if(strlen(part) != len)
|
||||
/* hostname with bad content */
|
||||
return CURLUE_MALFORMED_INPUT;
|
||||
return CURLUE_BAD_HOSTNAME;
|
||||
storep = &u->host;
|
||||
Curl_safefree(u->zoneid);
|
||||
break;
|
||||
@ -1505,7 +1529,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
|
||||
return CURLUE_BAD_PORT_NUMBER;
|
||||
if(*endp)
|
||||
/* weirdly provided number, not good! */
|
||||
return CURLUE_MALFORMED_INPUT;
|
||||
return CURLUE_BAD_PORT_NUMBER;
|
||||
storep = &u->port;
|
||||
}
|
||||
break;
|
||||
@ -1669,7 +1693,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
|
||||
else {
|
||||
if(hostname_check(u, (char *)newp)) {
|
||||
free((char *)newp);
|
||||
return CURLUE_MALFORMED_INPUT;
|
||||
return CURLUE_BAD_HOSTNAME;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -155,22 +155,34 @@ s6: CURLSHcode unknown
|
||||
u0: No error
|
||||
u1: An invalid CURLU pointer was passed as argument
|
||||
u2: An invalid 'part' argument was passed as argument
|
||||
u3: A malformed input was passed to a URL API function
|
||||
u4: The port number was not a decimal number between 0 and 65535
|
||||
u3: Malformed input to a URL function
|
||||
u4: Port number was not a decimal number between 0 and 65535
|
||||
u5: This libcurl build doesn't support the given URL scheme
|
||||
u6: URL decode error, most likely because of rubbish in the input
|
||||
u7: A memory function failed
|
||||
u8: Credentials was passed in the URL when prohibited
|
||||
u9: An unknown part ID was passed to a URL API function
|
||||
u10: There is no scheme part in the URL
|
||||
u11: There is no user part in the URL
|
||||
u12: There is no password part in the URL
|
||||
u13: There is no options part in the URL
|
||||
u14: There is no host part in the URL
|
||||
u15: There is no port part in the URL
|
||||
u16: There is no query part in the URL
|
||||
u17: There is no fragment part in the URL
|
||||
u18: CURLUcode unknown
|
||||
u10: No scheme part in the URL
|
||||
u11: No user part in the URL
|
||||
u12: No password part in the URL
|
||||
u13: No options part in the URL
|
||||
u14: No host part in the URL
|
||||
u15: No port part in the URL
|
||||
u16: No query part in the URL
|
||||
u17: No fragment part in the URL
|
||||
u18: No zoneid part in the URL
|
||||
u19: Bad file:// URL
|
||||
u20: Bad fragment
|
||||
u21: Bad hostname
|
||||
u22: Bad IPv6 address
|
||||
u23: Bad login part
|
||||
u24: Bad password
|
||||
u25: Bad path
|
||||
u26: Bad query
|
||||
u27: Bad scheme
|
||||
u28: Unsupported number of slashes
|
||||
u29: Bad user
|
||||
u30: CURLUcode unknown
|
||||
</stdout>
|
||||
</verify>
|
||||
|
||||
|
||||
@ -35,9 +35,9 @@ Set excessive URL lengths
|
||||
<stdout>
|
||||
CURLOPT_URL 10000000 bytes URL == 43
|
||||
CURLOPT_POSTFIELDS 10000000 bytes data == 0
|
||||
CURLUPART_URL 10000000 bytes URL == 3 (A malformed input was passed to a URL API function)
|
||||
CURLUPART_SCHEME 10000000 bytes scheme == 3 (A malformed input was passed to a URL API function)
|
||||
CURLUPART_USER 10000000 bytes user == 3 (A malformed input was passed to a URL API function)
|
||||
CURLUPART_URL 10000000 bytes URL == 3 (Malformed input to a URL function)
|
||||
CURLUPART_SCHEME 10000000 bytes scheme == 27 (Bad scheme)
|
||||
CURLUPART_USER 10000000 bytes user == 3 (Malformed input to a URL function)
|
||||
</stdout>
|
||||
</verify>
|
||||
|
||||
|
||||
@ -129,17 +129,21 @@ struct querycase {
|
||||
};
|
||||
|
||||
static const struct testcase get_parts_list[] ={
|
||||
{"https://user:password@example.net/get?this=and#but frag then", "",
|
||||
CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_FRAGMENT},
|
||||
{"https://user:password@example.net/get?this=and what", "",
|
||||
CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
|
||||
CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_QUERY},
|
||||
{"https://user:password@example.net/ge t?this=and-what", "",
|
||||
CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
|
||||
CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_PATH},
|
||||
{"https://user:pass word@example.net/get?this=and-what", "",
|
||||
CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
|
||||
CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_PASSWORD},
|
||||
{"https://u ser:password@example.net/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_BAD_LOGIN},
|
||||
/* no space allowed in scheme */
|
||||
{"htt ps://user:password@example.net/get?this=and-what", "",
|
||||
CURLU_NON_SUPPORT_SCHEME|CURLU_ALLOW_SPACE, 0, CURLUE_MALFORMED_INPUT},
|
||||
CURLU_NON_SUPPORT_SCHEME|CURLU_ALLOW_SPACE, 0, CURLUE_BAD_SCHEME},
|
||||
{"https://user:password@example.net/get?this=and what",
|
||||
"https | user | password | [13] | example.net | [15] | /get | "
|
||||
"this=and what | [17]",
|
||||
@ -213,9 +217,9 @@ static const struct testcase get_parts_list[] ={
|
||||
"com/color/?green#no-red",
|
||||
CURLU_DEFAULT_SCHEME, 0, CURLUE_OK },
|
||||
{"http://[ab.be:1]/x", "",
|
||||
CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
|
||||
CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_IPV6},
|
||||
{"http://[ab.be]/x", "",
|
||||
CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
|
||||
CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_IPV6},
|
||||
/* URL without host name */
|
||||
{"http://a:b@/x", "",
|
||||
CURLU_DEFAULT_SCHEME, 0, CURLUE_NO_HOST},
|
||||
@ -254,7 +258,7 @@ static const struct testcase get_parts_list[] ={
|
||||
0, 0, CURLUE_OK},
|
||||
{"file://hello.html",
|
||||
"",
|
||||
0, 0, CURLUE_MALFORMED_INPUT},
|
||||
0, 0, CURLUE_BAD_FILE_URL},
|
||||
{"http://HO0_-st/",
|
||||
"http | [11] | [12] | [13] | HO0_-st | [15] | / | [16] | [17]",
|
||||
0, 0, CURLUE_OK},
|
||||
@ -272,7 +276,7 @@ static const struct testcase get_parts_list[] ={
|
||||
0, 0, CURLUE_OK},
|
||||
{"file:/",
|
||||
"file | [11] | [12] | [13] | [14] | [15] | | [16] | [17]",
|
||||
0, 0, CURLUE_MALFORMED_INPUT},
|
||||
0, 0, CURLUE_BAD_FILE_URL},
|
||||
{"file://127.0.0.1/hello.html",
|
||||
"file | [11] | [12] | [13] | [14] | [15] | /hello.html | [16] | [17]",
|
||||
0, 0, CURLUE_OK},
|
||||
@ -295,9 +299,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},
|
||||
@ -357,7 +361,7 @@ static const struct testcase get_parts_list[] ={
|
||||
CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
|
||||
{"http:////user:password@example.com:1234/path/html?query=name#anchor",
|
||||
"",
|
||||
CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
|
||||
CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_SLASHES},
|
||||
{NULL, NULL, 0, 0, CURLUE_OK},
|
||||
};
|
||||
|
||||
@ -367,8 +371,8 @@ static const struct urltestcase get_url_list[] = {
|
||||
{"https://h%c", "https://h%25c/", 0, 0, CURLUE_OK},
|
||||
{"https://%%%%%%", "https://%25%25%25%25%25%25/", 0, 0, CURLUE_OK},
|
||||
{"https://%41", "https://A/", 0, 0, CURLUE_OK},
|
||||
{"https://%20", "", 0, 0, CURLUE_MALFORMED_INPUT},
|
||||
{"https://%41%0d", "", 0, 0, CURLUE_MALFORMED_INPUT},
|
||||
{"https://%20", "", 0, 0, CURLUE_BAD_HOSTNAME},
|
||||
{"https://%41%0d", "", 0, 0, CURLUE_BAD_HOSTNAME},
|
||||
{"https://%25", "https://%25/", 0, 0, CURLUE_OK},
|
||||
{"https://_%c0_", "https://_\xC0_/", 0, 0, CURLUE_OK},
|
||||
{"https://_%c0_", "https://_%C0_/", 0, CURLU_URLENCODE, CURLUE_OK},
|
||||
@ -385,7 +389,7 @@ static const struct urltestcase get_url_list[] = {
|
||||
{"https://+127.0.0.1", "https://%2B127.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.0x1000000", "https://1.0x1000000/", 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},
|
||||
@ -398,10 +402,10 @@ static const struct urltestcase get_url_list[] = {
|
||||
/* 41 bytes scheme is not allowed */
|
||||
{"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA://hostname/path",
|
||||
"",
|
||||
CURLU_NON_SUPPORT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
|
||||
CURLU_NON_SUPPORT_SCHEME, 0, CURLUE_BAD_SCHEME},
|
||||
{"https://[fe80::20c:29ff:fe9c:409b%]:1234",
|
||||
"",
|
||||
0, 0, CURLUE_MALFORMED_INPUT},
|
||||
0, 0, CURLUE_BAD_IPV6},
|
||||
{"https://[fe80::20c:29ff:fe9c:409b%25]:1234",
|
||||
"https://[fe80::20c:29ff:fe9c:409b%2525]:1234/",
|
||||
0, 0, CURLUE_OK},
|
||||
@ -437,14 +441,14 @@ 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\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",
|
||||
@ -464,7 +468,7 @@ static const struct urltestcase get_url_list[] = {
|
||||
0, 0, CURLUE_OK},
|
||||
{"file:./",
|
||||
"file://",
|
||||
0, 0, CURLUE_MALFORMED_INPUT},
|
||||
0, 0, CURLUE_BAD_SCHEME},
|
||||
{"http://example.com/hello/../here",
|
||||
"http://example.com/hello/../here",
|
||||
CURLU_PATH_AS_IS, 0, CURLUE_OK},
|
||||
@ -500,7 +504,7 @@ static const struct urltestcase get_url_list[] = {
|
||||
CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
|
||||
{"example.com/path/html",
|
||||
"",
|
||||
0, 0, CURLUE_MALFORMED_INPUT},
|
||||
0, 0, CURLUE_BAD_SCHEME},
|
||||
{"http://user:password@example.com:1234/path/html?query=name#anchor",
|
||||
"http://user:password@example.com:1234/path/html?query=name#anchor",
|
||||
0, 0, CURLUE_OK},
|
||||
@ -524,7 +528,7 @@ static const struct urltestcase get_url_list[] = {
|
||||
CURLU_NON_SUPPORT_SCHEME, 0, CURLUE_OK},
|
||||
{"custom-scheme://?expected=test-bad",
|
||||
"",
|
||||
CURLU_NON_SUPPORT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
|
||||
CURLU_NON_SUPPORT_SCHEME, 0, CURLUE_NO_HOST},
|
||||
{"custom-scheme://?expected=test-new-good",
|
||||
"custom-scheme:///?expected=test-new-good",
|
||||
CURLU_NON_SUPPORT_SCHEME | CURLU_NO_AUTHORITY, 0, CURLUE_OK},
|
||||
@ -565,7 +569,7 @@ static const struct setcase set_parts_list[] = {
|
||||
/* Set a 41 bytes scheme. That's too long so the old scheme remains set. */
|
||||
"scheme=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbc,",
|
||||
"https://example.com/",
|
||||
0, CURLU_NON_SUPPORT_SCHEME, CURLUE_OK, CURLUE_MALFORMED_INPUT},
|
||||
0, CURLU_NON_SUPPORT_SCHEME, CURLUE_OK, CURLUE_BAD_SCHEME},
|
||||
{"https://example.com/",
|
||||
/* set a 40 bytes scheme */
|
||||
"scheme=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,",
|
||||
@ -586,7 +590,7 @@ static const struct setcase set_parts_list[] = {
|
||||
{"https://host:1234/",
|
||||
"port=56 78,",
|
||||
"https://host:1234/",
|
||||
0, 0, CURLUE_OK, CURLUE_MALFORMED_INPUT},
|
||||
0, 0, CURLUE_OK, CURLUE_BAD_PORT_NUMBER},
|
||||
{"https://host:1234/",
|
||||
"port=0,",
|
||||
"https://host:1234/",
|
||||
@ -619,7 +623,7 @@ static const struct setcase set_parts_list[] = {
|
||||
{NULL,
|
||||
"scheme=https,host= ,path= ,user= ,password= ,query= ,fragment= ,",
|
||||
"[nothing]",
|
||||
0, CURLU_URLENCODE, CURLUE_OK, CURLUE_MALFORMED_INPUT},
|
||||
0, CURLU_URLENCODE, CURLUE_OK, CURLUE_BAD_HOSTNAME},
|
||||
{NULL,
|
||||
"scheme=https,host=foobar,path=/this /path /is /here,",
|
||||
"https://foobar/this%20/path%20/is%20/here",
|
||||
@ -688,7 +692,7 @@ static const struct setcase set_parts_list[] = {
|
||||
"host=\"\",",
|
||||
"custom-scheme://host/",
|
||||
CURLU_NON_SUPPORT_SCHEME, CURLU_NON_SUPPORT_SCHEME, CURLUE_OK,
|
||||
CURLUE_MALFORMED_INPUT},
|
||||
CURLUE_BAD_HOSTNAME},
|
||||
{"custom-scheme://host",
|
||||
"host=\"\",",
|
||||
"custom-scheme:///",
|
||||
@ -1164,10 +1168,64 @@ static int scopeid(void)
|
||||
return error;
|
||||
}
|
||||
|
||||
static int get_nothing(void)
|
||||
{
|
||||
CURLU *u = curl_url();
|
||||
if(u) {
|
||||
char *p;
|
||||
CURLUcode rc;
|
||||
|
||||
rc = curl_url_get(u, CURLUPART_SCHEME, &p, 0);
|
||||
if(rc != CURLUE_NO_SCHEME)
|
||||
fprintf(stderr, "unexpected return code line %u\n", __LINE__);
|
||||
|
||||
rc = curl_url_get(u, CURLUPART_HOST, &p, 0);
|
||||
if(rc != CURLUE_NO_HOST)
|
||||
fprintf(stderr, "unexpected return code line %u\n", __LINE__);
|
||||
|
||||
rc = curl_url_get(u, CURLUPART_USER, &p, 0);
|
||||
if(rc != CURLUE_NO_USER)
|
||||
fprintf(stderr, "unexpected return code line %u\n", __LINE__);
|
||||
|
||||
rc = curl_url_get(u, CURLUPART_PASSWORD, &p, 0);
|
||||
if(rc != CURLUE_NO_PASSWORD)
|
||||
fprintf(stderr, "unexpected return code line %u\n", __LINE__);
|
||||
|
||||
rc = curl_url_get(u, CURLUPART_OPTIONS, &p, 0);
|
||||
if(rc != CURLUE_NO_OPTIONS)
|
||||
fprintf(stderr, "unexpected return code line %u\n", __LINE__);
|
||||
|
||||
rc = curl_url_get(u, CURLUPART_PATH, &p, 0);
|
||||
if(rc != CURLUE_OK)
|
||||
fprintf(stderr, "unexpected return code line %u\n", __LINE__);
|
||||
else
|
||||
curl_free(p);
|
||||
|
||||
rc = curl_url_get(u, CURLUPART_QUERY, &p, 0);
|
||||
if(rc != CURLUE_NO_QUERY)
|
||||
fprintf(stderr, "unexpected return code line %u\n", __LINE__);
|
||||
|
||||
rc = curl_url_get(u, CURLUPART_FRAGMENT, &p, 0);
|
||||
if(rc != CURLUE_NO_FRAGMENT)
|
||||
fprintf(stderr, "unexpected return code line %u\n", __LINE__);
|
||||
|
||||
rc = curl_url_get(u, CURLUPART_ZONEID, &p, 0);
|
||||
if(rc != CURLUE_OK)
|
||||
fprintf(stderr, "unexpected return code %u on line %u\n", (int)rc,
|
||||
__LINE__);
|
||||
|
||||
curl_url_cleanup(u);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test(char *URL)
|
||||
{
|
||||
(void)URL; /* not used */
|
||||
|
||||
if(get_nothing())
|
||||
return 7;
|
||||
|
||||
if(scopeid())
|
||||
return 6;
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user