diff --git a/lib/urlapi.c b/lib/urlapi.c index 00e12e645e..3d4a3f94b8 100644 --- a/lib/urlapi.c +++ b/lib/urlapi.c @@ -1991,7 +1991,23 @@ nomem: /* Skip hostname check, it is allowed to be empty. */ } else { - if(!n || hostname_check(u, (char *)newp, n)) { + bool bad = FALSE; + if(!n) + bad = TRUE; /* empty hostname is not okay */ + else if(!urlencode) { + /* if the host name part was not URL encoded here, it was set ready + URL encoded so we need to decode it to check */ + size_t dlen; + char *decoded = NULL; + CURLcode result = + Curl_urldecode(newp, n, &decoded, &dlen, REJECT_CTRL); + if(result || hostname_check(u, decoded, dlen)) + bad = TRUE; + free(decoded); + } + else if(hostname_check(u, (char *)newp, n)) + bad = TRUE; + if(bad) { Curl_dyn_free(&enc); return CURLUE_BAD_HOSTNAME; } diff --git a/tests/libtest/lib1560.c b/tests/libtest/lib1560.c index 0109d6edd2..2956ce9b50 100644 --- a/tests/libtest/lib1560.c +++ b/tests/libtest/lib1560.c @@ -838,6 +838,14 @@ static const struct setgetcase setget_parts_list[] = { /* !checksrc! disable SPACEBEFORECOMMA 1 */ static const struct setcase set_parts_list[] = { + {"https://example.com/", + "host=%43url.se,", + "https://%43url.se/", + 0, 0, CURLUE_OK, CURLUE_OK}, + {"https://example.com/", + "host=%25url.se,", + "", + 0, 0, CURLUE_OK, CURLUE_BAD_HOSTNAME}, {"https://example.com/?param=value", "query=\"\",", "https://example.com/",