diff options
author | Curl Upstream <curl-library@lists.haxx.se> | 2022-01-04 23:35:58 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2022-01-07 16:41:33 (GMT) |
commit | a1f6ec647cfab8d613897562f8ee5f81a8f6b68d (patch) | |
tree | 23868e745531ca352f4ae8df37dc242b8ed6f80e /lib/urlapi.c | |
parent | a4ad12d8435cdd4ab7301d21215c40348c04c8ed (diff) | |
download | CMake-a1f6ec647cfab8d613897562f8ee5f81a8f6b68d.zip CMake-a1f6ec647cfab8d613897562f8ee5f81a8f6b68d.tar.gz CMake-a1f6ec647cfab8d613897562f8ee5f81a8f6b68d.tar.bz2 |
curl 2022-01-05 (801bd513)
Code extracted from:
https://github.com/curl/curl.git
at commit 801bd5138ce31aa0d906fa4e2eabfc599d74e793 (curl-7_81_0).
Diffstat (limited to 'lib/urlapi.c')
-rw-r--r-- | lib/urlapi.c | 402 |
1 files changed, 272 insertions, 130 deletions
diff --git a/lib/urlapi.c b/lib/urlapi.c index 7f03862..d29aeb2 100644 --- a/lib/urlapi.c +++ b/lib/urlapi.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -30,6 +30,7 @@ #include "escape.h" #include "curl_ctype.h" #include "inet_pton.h" +#include "inet_ntop.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -50,6 +51,9 @@ ((str)[1] == ':' || (str)[1] == '|') && \ ((str)[2] == '/' || (str)[2] == '\\' || (str)[2] == 0)) +/* scheme is not URL encoded, the longest libcurl supported ones are... */ +#define MAX_SCHEME_LEN 40 + /* Internal representation of CURLU. Point to URL-encoded strings. */ struct Curl_URL { char *scheme; @@ -157,23 +161,23 @@ static size_t strlen_url(const char *url, bool relative) continue; } - switch(*ptr) { - case '?': - left = FALSE; - /* FALLTHROUGH */ - default: - if(urlchar_needs_escaping(*ptr)) - newlen += 2; - newlen++; - break; - case ' ': + if(*ptr == ' ') { if(left) newlen += 3; else newlen++; - break; + continue; } + + if (*ptr == '?') + left = FALSE; + + if(urlchar_needs_escaping(*ptr)) + newlen += 2; + + newlen++; } + return newlen; } @@ -202,19 +206,7 @@ static void strcpy_url(char *output, const char *url, bool relative) continue; } - switch(*iptr) { - case '?': - left = FALSE; - /* FALLTHROUGH */ - default: - if(urlchar_needs_escaping(*iptr)) { - msnprintf(optr, 4, "%%%02x", *iptr); - optr += 3; - } - else - *optr++=*iptr; - break; - case ' ': + if(*iptr == ' ') { if(left) { *optr++='%'; /* add a '%' */ *optr++='2'; /* add a '2' */ @@ -222,41 +214,58 @@ static void strcpy_url(char *output, const char *url, bool relative) } else *optr++='+'; /* add a '+' here */ - break; + continue; } + + if(*iptr == '?') + left = FALSE; + + if(urlchar_needs_escaping(*iptr)) { + msnprintf(optr, 4, "%%%02x", *iptr); + optr += 3; + } + else + *optr++ = *iptr; } *optr = 0; /* null-terminate output buffer */ } /* - * Returns true if the given URL is absolute (as opposed to relative) within - * the buffer size. Returns the scheme in the buffer if TRUE and 'buf' is - * non-NULL. + * Returns true if the given URL is absolute (as opposed to relative). Returns + * the scheme in the buffer if TRUE and 'buf' is non-NULL. The buflen must + * be larger than MAX_SCHEME_LEN if buf is set. */ bool Curl_is_absolute_url(const char *url, char *buf, size_t buflen) { size_t i; + DEBUGASSERT(!buf || (buflen > MAX_SCHEME_LEN)); + (void)buflen; /* only used in debug-builds */ + if(buf) + buf[0] = 0; /* always leave a defined value in buf */ #ifdef WIN32 if(STARTS_WITH_DRIVE_PREFIX(url)) return FALSE; #endif - for(i = 0; i < buflen && url[i]; ++i) { + for(i = 0; i < MAX_SCHEME_LEN; ++i) { char s = url[i]; - if((s == ':') && (url[i + 1] == '/')) { - if(buf) - buf[i] = 0; - return TRUE; - } - /* RFC 3986 3.1 explains: - scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) - */ - else if(ISALNUM(s) || (s == '+') || (s == '-') || (s == '.') ) { - if(buf) - buf[i] = (char)TOLOWER(s); + if(s && (ISALNUM(s) || (s == '+') || (s == '-') || (s == '.') )) { + /* RFC 3986 3.1 explains: + scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) + */ } - else + else { break; + } + } + if(i && (url[i] == ':') && (url[i + 1] == '/')) { + if(buf) { + buf[i] = 0; + while(i--) { + buf[i] = (char)TOLOWER(url[i]); + } + } + return TRUE; } return FALSE; } @@ -420,6 +429,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() * @@ -467,7 +499,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; } @@ -477,15 +509,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: @@ -493,6 +538,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; } @@ -516,19 +564,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; @@ -558,9 +606,7 @@ UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, char *hostname, port = strtol(portptr + 1, &rest, 10); /* Port number must be decimal */ - if((port <= 0) || (port > 0xffff)) - /* Single unix standard says port numbers are 16 bits long, but we don't - treat port zero as OK. */ + if(port > 0xffff) return CURLUE_BAD_PORT_NUMBER; if(rest[0]) @@ -579,46 +625,20 @@ 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; size_t hlen = strlen(hostname); if(hostname[0] == '[') { -#ifdef ENABLE_IPV6 - char dest[16]; /* fits a binary IPv6 address */ -#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); @@ -635,6 +655,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); @@ -644,22 +665,34 @@ 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; - hostname[hlen] = ']'; /* restore ending bracket */ + { + char dest[16]; /* fits a binary IPv6 address */ + char norm[MAX_IPADR_LEN]; + hostname[hlen] = 0; /* end the address there */ + if(1 != Curl_inet_pton(AF_INET6, hostname, dest)) + return CURLUE_BAD_IPV6; + + /* check if it can be done shorter */ + if(Curl_inet_ntop(AF_INET6, dest, norm, sizeof(norm)) && + (strlen(norm) < hlen)) { + strcpy(hostname, norm); + hlen = strlen(norm); + hostname[hlen + 1] = 0; + } + hostname[hlen] = ']'; /* restore ending bracket */ + } #endif } else { /* letters from the second string is not ok */ - len = strcspn(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; @@ -756,10 +789,35 @@ static bool ipv4_normalize(const char *hostname, char *outp, size_t olen) return TRUE; } +/* return strdup'ed version in 'outp', possibly percent decoded */ +static CURLUcode decode_host(char *hostname, char **outp) +{ + char *per = NULL; + if(hostname[0] != '[') + /* only decode if not an ipv6 numerical */ + per = strchr(hostname, '%'); + if(!per) { + *outp = strdup(hostname); + if(!*outp) + return CURLUE_OUT_OF_MEMORY; + } + else { + /* might be encoded */ + size_t dlen; + CURLcode result = Curl_urldecode(NULL, hostname, 0, + outp, &dlen, REJECT_CTRL); + if(result) + return CURLUE_BAD_HOSTNAME; + } + + return CURLUE_OK; +} + static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags) { char *path; bool path_alloced = FALSE; + bool uncpath = FALSE; char *hostname; char *query = NULL; char *fragment = NULL; @@ -794,11 +852,14 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags) } /* handle the file: scheme */ - if(url_has_scheme && strcasecompare(schemebuf, "file")) { + if(url_has_scheme && !strcmp(schemebuf, "file")) { + if(urllen <= 6) + /* file:/ is not enough to actually be a complete file: URL */ + return CURLUE_BAD_FILE_URL; + /* path has been allocated large enough to hold this */ strcpy(path, &url[5]); - hostname = NULL; /* no host for file: URLs */ u->scheme = strdup("file"); if(!u->scheme) return CURLUE_OUT_OF_MEMORY; @@ -820,10 +881,13 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags) * * o the hostname matches "localhost" (case-insensitively), or * - * o the hostname is a FQDN that resolves to this machine. + * o the hostname is a FQDN that resolves to this machine, or + * + * o it is an UNC String transformed to an URI (Windows only, RFC 8089 + * Appendix E.3). * * For brevity, we only consider URLs with empty, "localhost", or - * "127.0.0.1" hostnames as local. + * "127.0.0.1" hostnames as local, otherwise as an UNC String. * * Additionally, there is an exception for URLs with a Windows drive * letter in the authority (which was accidentally omitted from RFC 8089 @@ -832,25 +896,50 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags) if(ptr[0] != '/' && !STARTS_WITH_URL_DRIVE_PREFIX(ptr)) { /* the URL includes a host name, it must match "localhost" or "127.0.0.1" to be valid */ - if(!checkprefix("localhost/", ptr) && - !checkprefix("127.0.0.1/", ptr)) { + if(checkprefix("localhost/", ptr) || + checkprefix("127.0.0.1/", ptr)) { + ptr += 9; /* now points to the slash after the host */ + } + else { +#if defined(WIN32) + size_t len; + + /* the host name, NetBIOS computer name, can not contain disallowed + chars, and the delimiting slash character must be appended to the + host name */ + path = strpbrk(ptr, "/\\:*?\"<>|"); + if(!path || *path != '/') + return CURLUE_BAD_FILE_URL; + + len = path - ptr; + if(len) { + memcpy(hostname, ptr, len); + hostname[len] = 0; + uncpath = TRUE; + } + + ptr -= 2; /* now points to the // before the host in UNC */ +#else /* Invalid file://hostname/, expected localhost or 127.0.0.1 or none */ - return CURLUE_MALFORMED_INPUT; + return CURLUE_BAD_FILE_URL; +#endif } - ptr += 9; /* now points to the slash after the host */ } path = ptr; } + if(!uncpath) + hostname = NULL; /* no host for file: URLs by default */ + #if !defined(MSDOS) && !defined(WIN32) && !defined(__CYGWIN__) /* Don't allow Windows drive letters when not in Windows. * This catches both "file:/c:" and "file:c:" */ 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 */ @@ -877,7 +966,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) && @@ -885,13 +974,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; @@ -902,7 +991,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; @@ -912,7 +1002,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); @@ -926,9 +1016,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); @@ -942,6 +1029,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) @@ -952,12 +1041,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; @@ -987,12 +1081,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; @@ -1001,22 +1093,27 @@ 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(""); } else { - result = hostname_check(u, hostname); - if(result) - return result; + if(ipv4_normalize(hostname, normalized_ipv4, sizeof(normalized_ipv4))) + u->host = strdup(normalized_ipv4); + else { + result = decode_host(hostname, &u->host); + if(result) + return result; + result = hostname_check(u, u->host); + if(result) + return result; + } } - - if(ipv4_normalize(hostname, normalized_ipv4, sizeof(normalized_ipv4))) - u->host = strdup(normalized_ipv4); - else - u->host = strdup(hostname); if(!u->host) return CURLUE_OUT_OF_MEMORY; - if((flags & CURLU_GUESS_SCHEME) && !schemep) { /* legacy curl-style guess based on host name */ if(checkprefix("ftp.", hostname)) @@ -1111,6 +1208,7 @@ CURLUcode curl_url_get(CURLU *u, CURLUPart what, CURLUcode ifmissing = CURLUE_UNKNOWN_PART; char portbuf[7]; bool urldecode = (flags & CURLU_URLDECODE)?1:0; + bool urlencode = (flags & CURLU_URLENCODE)?1:0; bool plusdecode = FALSE; (void)flags; if(!u) @@ -1143,6 +1241,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; @@ -1228,16 +1327,54 @@ CURLUcode curl_url_get(CURLU *u, CURLUPart what, if(h && !(h->flags & PROTOPT_URLOPTIONS)) options = NULL; - if((u->host[0] == '[') && u->zoneid) { - /* make it '[ host %25 zoneid ]' */ - size_t hostlen = strlen(u->host); - size_t alen = hostlen + 3 + strlen(u->zoneid) + 1; - allochost = malloc(alen); + if(u->host[0] == '[') { + if(u->zoneid) { + /* make it '[ host %25 zoneid ]' */ + size_t hostlen = strlen(u->host); + size_t alen = hostlen + 3 + strlen(u->zoneid) + 1; + allochost = malloc(alen); + if(!allochost) + return CURLUE_OUT_OF_MEMORY; + memcpy(allochost, u->host, hostlen - 1); + msnprintf(&allochost[hostlen - 1], alen - hostlen + 1, + "%%25%s]", u->zoneid); + } + } + else if(urlencode) { + allochost = curl_easy_escape(NULL, u->host, 0); if(!allochost) return CURLUE_OUT_OF_MEMORY; - memcpy(allochost, u->host, hostlen - 1); - msnprintf(&allochost[hostlen - 1], alen - hostlen + 1, - "%%25%s]", u->zoneid); + } + else { + /* only encode '%' in output host name */ + char *host = u->host; + size_t pcount = 0; + /* first, count number of percents present in the name */ + while(*host) { + if(*host == '%') + pcount++; + host++; + } + /* if there were percents, encode the host name */ + if(pcount) { + size_t hostlen = strlen(u->host); + size_t alen = hostlen + 2 * pcount + 1; + char *o = allochost = malloc(alen); + if(!allochost) + return CURLUE_OUT_OF_MEMORY; + + host = u->host; + while(*host) { + if(*host == '%') { + memcpy(o, "%25", 3); + o += 3; + host++; + continue; + } + *o++ = *host++; + } + *o = '\0'; + } } url = aprintf("%s://%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", @@ -1362,7 +1499,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)) @@ -1379,10 +1516,15 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what, case CURLUPART_OPTIONS: storep = &u->options; break; - case CURLUPART_HOST: + case CURLUPART_HOST: { + size_t len = strcspn(part, " \r\n"); + if(strlen(part) != len) + /* hostname with bad content */ + return CURLUE_BAD_HOSTNAME; storep = &u->host; Curl_safefree(u->zoneid); break; + } case CURLUPART_ZONEID: storep = &u->zoneid; break; @@ -1395,7 +1537,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; @@ -1424,7 +1566,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what, char *redired_url; CURLU *handle2; - if(Curl_is_absolute_url(part, NULL, MAX_SCHEME_LEN + 1)) { + if(Curl_is_absolute_url(part, NULL, 0)) { handle2 = curl_url(); if(!handle2) return CURLUE_OUT_OF_MEMORY; @@ -1559,7 +1701,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; } } } |