urlapi: redirecting to "" is considered fine

If the CURLU handle already holds a proper URL, otherwise it is an
error.

Verified by test 1560

Fixes #17188
Reported-by: zopsicle on github
Closes #17189
This commit is contained in:
Daniel Stenberg 2025-04-25 16:22:24 +02:00
parent 01b177721b
commit 15839450be
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
3 changed files with 27 additions and 3 deletions

View file

@ -79,7 +79,7 @@ is replaced with the components of the newly set URL.
Pass a pointer to a null-terminated string to the *url* parameter. The string
must point to a correctly formatted "RFC 3986+" URL or be a NULL pointer. The
URL parser only understands and parses the subset of URLS that are
"hierarchical" and therefore contain a :// separator - not the ones that are
"hierarchical" and therefore contain a `://` separator - not the ones that are
normally specified with only a colon separator.
By default this API only parses URLs using schemes for protocols that are
@ -93,6 +93,10 @@ the URL.
When a full URL is set (parsed), the hostname component is stored URL decoded.
It is considered fine to set a blank URL ("") as a redirect, but not as a
normal URL. Therefore, setting a "" URL works fine if the handle already holds
a URL, otherwise it triggers an error.
## CURLUPART_SCHEME
Scheme cannot be URL decoded on set. libcurl only accepts setting schemes up

View file

@ -1770,9 +1770,17 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
CURLUcode uc;
char *oldurl;
if(!nalloc)
/* a blank URL is not a valid URL */
if(!nalloc) {
/* a blank URL is not a valid URL unless we already have a complete one
and this is a redirect */
if(!curl_url_get(u, CURLUPART_URL, &oldurl, flags)) {
/* success, meaning the "" is a fine relative URL, but nothing
changes */
free(oldurl);
return CURLUE_OK;
}
return CURLUE_MALFORMED_INPUT;
}
/* if the new thing is absolute or the old one is not (we could not get an
* absolute URL in 'oldurl'), then replace the existing with the new. */

View file

@ -875,6 +875,14 @@ static const struct setgetcase setget_parts_list[] = {
/* !checksrc! disable SPACEBEFORECOMMA 1 */
static const struct setcase set_parts_list[] = {
{NULL, /* start fresh! */
"scheme=https,path=/,url=\"\",", /* incomplete url, redirect to "" */
"https://example.com/",
0, 0, CURLUE_OK, CURLUE_MALFORMED_INPUT},
{NULL, /* start fresh! */
"scheme=https,host=example.com,path=/,url=\"\",", /* redirect to "" */
"https://example.com/",
0, 0, CURLUE_OK, CURLUE_OK},
{"https://example.com/",
"path=one\ntwo,",
"https://example.com/one\ntwo",
@ -1193,6 +1201,10 @@ static CURLUcode updateurl(CURLU *u, const char *cmd, unsigned int setflags)
}
static const struct redircase set_url_list[] = {
{"https://example.com",
"", /* blank redirect */
"https://example.com/",
0, 0, CURLUE_OK },
{"http://firstplace.example.com/want/1314",
"//somewhere.example.com/reply/1314",
"http://somewhere.example.com/reply/1314",