From: Daniel Stenberg Date: Fri, 25 Apr 2025 14:22:24 +0000 (+0200) Subject: urlapi: redirecting to "" is considered fine X-Git-Tag: curl-8_14_0~207 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=15839450be1640580df1c3bf449f0b7e73684419;p=thirdparty%2Fcurl.git 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 --- diff --git a/docs/libcurl/curl_url_set.md b/docs/libcurl/curl_url_set.md index 6081a72511..5758a105b1 100644 --- a/docs/libcurl/curl_url_set.md +++ b/docs/libcurl/curl_url_set.md @@ -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 diff --git a/lib/urlapi.c b/lib/urlapi.c index 88cfa82418..a30d60420b 100644 --- a/lib/urlapi.c +++ b/lib/urlapi.c @@ -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. */ diff --git a/tests/libtest/lib1560.c b/tests/libtest/lib1560.c index 3d93163a9a..01e9c4108c 100644 --- a/tests/libtest/lib1560.c +++ b/tests/libtest/lib1560.c @@ -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",