]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
urlapi: redirecting to "" is considered fine
authorDaniel Stenberg <daniel@haxx.se>
Fri, 25 Apr 2025 14:22:24 +0000 (16:22 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Fri, 25 Apr 2025 20:38:04 +0000 (22:38 +0200)
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

docs/libcurl/curl_url_set.md
lib/urlapi.c
tests/libtest/lib1560.c

index 6081a72511dcfd68698f3495500dad445217aeef..5758a105b11523c1319e14f2d7072ebecb27480e 100644 (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
index 88cfa824183e4b4b80032587dc5b94ce2f5837f5..a30d60420becffdd3c85feea9e16baaf781be2b3 100644 (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. */
index 3d93163a9a1dd3119cf0e79e15ced72811c02d29..01e9c4108cba4ef419e95772b00d3f5dc259627b 100644 (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",