]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
tool_operate: Fix error codes on bad URL & OOM
authorDan Fandrich <dan@coneharvesters.com>
Sun, 5 Feb 2023 00:05:35 +0000 (16:05 -0800)
committerDaniel Stenberg <daniel@haxx.se>
Tue, 7 Feb 2023 07:20:04 +0000 (08:20 +0100)
curl would erroneously report CURLE_OUT_OF_MEMORY in some cases instead
of CURLE_URL_MALFORMAT. In other cases, it would erroneously return
CURLE_URL_MALFORMAT instead of CURLE_OUT_OF_MEMORY.  Add a test case to
test the former condition.

Fixes #10130
Closes #10414

src/tool_operate.c
src/tool_operhlp.c
src/tool_operhlp.h
tests/data/Makefile.inc
tests/data/test1469 [new file with mode: 0644]

index 2fccfda671ff4356792c87feb830a5c9e7e5b8c9..ae17586d8c57d57d0ea149edeb1cf67302d64268 100644 (file)
@@ -1209,21 +1209,26 @@ static CURLcode single_transfer(struct GlobalConfig *global,
           CURLU *uh = curl_url();
           if(uh) {
             char *updated;
-            if(curl_url_set(uh, CURLUPART_URL, per->this_url,
-                            CURLU_GUESS_SCHEME)) {
-              result = CURLE_FAILED_INIT;
+            CURLUcode uerr;
+            uerr = curl_url_set(uh, CURLUPART_URL, per->this_url,
+                            CURLU_GUESS_SCHEME);
+            if(uerr) {
+              result = urlerr_cvt(uerr);
               errorf(global, "(%d) Could not parse the URL, "
                      "failed to set query\n", result);
               config->synthetic_error = TRUE;
             }
-            else if(curl_url_set(uh, CURLUPART_QUERY, q, CURLU_APPENDQUERY) ||
-                    curl_url_get(uh, CURLUPART_URL, &updated,
-                                 CURLU_GUESS_SCHEME)) {
-              result = CURLE_OUT_OF_MEMORY;
-            }
             else {
-              Curl_safefree(per->this_url); /* free previous URL */
-              per->this_url = updated; /* use our new URL instead! */
+              uerr = curl_url_set(uh, CURLUPART_QUERY, q, CURLU_APPENDQUERY);
+              if(!uerr)
+                uerr = curl_url_get(uh, CURLUPART_URL, &updated,
+                                   CURLU_GUESS_SCHEME);
+              if(uerr)
+                result = urlerr_cvt(uerr);
+              else {
+                Curl_safefree(per->this_url); /* free previous URL */
+                per->this_url = updated; /* use our new URL instead! */
+              }
             }
             curl_url_cleanup(uh);
             if(result)
index f6ae04d78f8ebbe66b15259854b25a88e03b941f..02039413ca87fb4b8d98d37c2ef65e8efcbc2db0 100644 (file)
@@ -71,22 +71,43 @@ bool stdin_upload(const char *uploadfile)
           !strcmp(uploadfile, ".")) ? TRUE : FALSE;
 }
 
+/* Convert a CURLUcode into a CURLcode */
+CURLcode urlerr_cvt(CURLUcode ucode)
+{
+  if(ucode == CURLUE_OUT_OF_MEMORY)
+    return CURLE_OUT_OF_MEMORY;
+  else if(ucode == CURLUE_UNSUPPORTED_SCHEME)
+    return CURLE_UNSUPPORTED_PROTOCOL;
+  else if(ucode == CURLUE_LACKS_IDN)
+    return CURLE_NOT_BUILT_IN;
+  else if(ucode == CURLUE_BAD_HANDLE)
+    return CURLE_BAD_FUNCTION_ARGUMENT;
+  return CURLE_URL_MALFORMAT;
+}
+
 /*
  * Adds the file name to the URL if it doesn't already have one.
  * url will be freed before return if the returned pointer is different
  */
 CURLcode add_file_name_to_url(CURL *curl, char **inurlp, const char *filename)
 {
-  CURLcode result = CURLE_OUT_OF_MEMORY;
+  CURLcode result = CURLE_URL_MALFORMAT;
+  CURLUcode uerr;
   CURLU *uh = curl_url();
   char *path = NULL;
   if(uh) {
     char *ptr;
-    if(curl_url_set(uh, CURLUPART_URL, *inurlp,
-                    CURLU_GUESS_SCHEME|CURLU_NON_SUPPORT_SCHEME))
+    uerr = curl_url_set(uh, CURLUPART_URL, *inurlp,
+                    CURLU_GUESS_SCHEME|CURLU_NON_SUPPORT_SCHEME);
+    if(uerr) {
+      result = urlerr_cvt(uerr);
       goto fail;
-    if(curl_url_get(uh, CURLUPART_PATH, &path, 0))
+    }
+    uerr = curl_url_get(uh, CURLUPART_PATH, &path, 0);
+    if(uerr) {
+      result = urlerr_cvt(uerr);
       goto fail;
+    }
 
     ptr = strrchr(path, '/');
     if(!ptr || !*++ptr) {
@@ -111,7 +132,6 @@ CURLcode add_file_name_to_url(CURL *curl, char **inurlp, const char *filename)
       if(encfile) {
         char *newpath;
         char *newurl;
-        CURLUcode uerr;
         if(ptr)
           /* there is a trailing slash on the path */
           newpath = aprintf("%s%s", path, encfile);
@@ -125,10 +145,15 @@ CURLcode add_file_name_to_url(CURL *curl, char **inurlp, const char *filename)
           goto fail;
         uerr = curl_url_set(uh, CURLUPART_PATH, newpath, 0);
         free(newpath);
-        if(uerr)
+        if(uerr) {
+          result = urlerr_cvt(uerr);
           goto fail;
-        if(curl_url_get(uh, CURLUPART_URL, &newurl, CURLU_DEFAULT_SCHEME))
+        }
+        uerr = curl_url_get(uh, CURLUPART_URL, &newurl, CURLU_DEFAULT_SCHEME);
+        if(uerr) {
+          result = urlerr_cvt(uerr);
           goto fail;
+        }
         free(*inurlp);
         *inurlp = newurl;
         result = CURLE_OK;
@@ -153,32 +178,35 @@ CURLcode get_url_file_name(char **filename, const char *url)
   const char *pc, *pc2;
   CURLU *uh = curl_url();
   char *path = NULL;
+  CURLUcode uerr;
 
   if(!uh)
     return CURLE_OUT_OF_MEMORY;
 
   *filename = NULL;
 
-  if(!curl_url_set(uh, CURLUPART_URL, url, CURLU_GUESS_SCHEME) &&
-     !curl_url_get(uh, CURLUPART_PATH, &path, 0)) {
-    curl_url_cleanup(uh);
+  uerr = curl_url_set(uh, CURLUPART_URL, url, CURLU_GUESS_SCHEME);
+  if(!uerr) {
+    uerr = curl_url_get(uh, CURLUPART_PATH, &path, 0);
+    if(!uerr) {
+      curl_url_cleanup(uh);
 
-    pc = strrchr(path, '/');
-    pc2 = strrchr(pc ? pc + 1 : path, '\\');
-    if(pc2)
-      pc = pc2;
+      pc = strrchr(path, '/');
+      pc2 = strrchr(pc ? pc + 1 : path, '\\');
+      if(pc2)
+        pc = pc2;
 
-    if(pc)
-      /* duplicate the string beyond the slash */
-      pc++;
-    else
-      /* no slash => empty string */
-      pc = "";
+      if(pc)
+        /* duplicate the string beyond the slash */
+        pc++;
+      else
+        /* no slash => empty string */
+        pc = "";
 
-    *filename = strdup(pc);
-    curl_free(path);
-    if(!*filename)
-      return CURLE_OUT_OF_MEMORY;
+      *filename = strdup(pc);
+      curl_free(path);
+      if(!*filename)
+        return CURLE_OUT_OF_MEMORY;
 
 #if defined(MSDOS) || defined(WIN32)
     {
@@ -191,25 +219,26 @@ CURLcode get_url_file_name(char **filename, const char *url)
     }
 #endif /* MSDOS || WIN32 */
 
-    /* in case we built debug enabled, we allow an environment variable
-     * named CURL_TESTDIR to prefix the given file name to put it into a
-     * specific directory
-     */
+      /* in case we built debug enabled, we allow an environment variable
+       * named CURL_TESTDIR to prefix the given file name to put it into a
+       * specific directory
+       */
 #ifdef DEBUGBUILD
-    {
-      char *tdir = curlx_getenv("CURL_TESTDIR");
-      if(tdir) {
-        char *alt = aprintf("%s/%s", tdir, *filename);
-        Curl_safefree(*filename);
-        *filename = alt;
-        curl_free(tdir);
-        if(!*filename)
-          return CURLE_OUT_OF_MEMORY;
+      {
+        char *tdir = curlx_getenv("CURL_TESTDIR");
+        if(tdir) {
+          char *alt = aprintf("%s/%s", tdir, *filename);
+          Curl_safefree(*filename);
+          *filename = alt;
+          curl_free(tdir);
+          if(!*filename)
+            return CURLE_OUT_OF_MEMORY;
+        }
       }
-    }
 #endif
-    return CURLE_OK;
+      return CURLE_OK;
+    }
   }
   curl_url_cleanup(uh);
-  return CURLE_URL_MALFORMAT;
+  return urlerr_cvt(uerr);
 }
index 1f2c19c661c7fe63e3007a41721531c3d01c70a3..1d56fa04082c0c0efffe3240fc21c1e640358596 100644 (file)
@@ -37,4 +37,6 @@ CURLcode add_file_name_to_url(CURL *curl, char **inurlp, const char *filename);
 
 CURLcode get_url_file_name(char **filename, const char *url);
 
+CURLcode urlerr_cvt(CURLUcode ucode);
+
 #endif /* HEADER_CURL_TOOL_OPERHLP_H */
index ffcd93620ba98ac75815b37ef8565b7da8755834..435ea77ae65ced5c7a6ba149506c873bf71fc795 100644 (file)
@@ -185,7 +185,7 @@ test1432 test1433 test1434 test1435 test1436 test1437 test1438 test1439 \
 test1440 test1441 test1442 test1443 test1444 test1445 test1446 test1447 \
 test1448 test1449 test1450 test1451 test1452 test1453 test1454 test1455 \
 test1456 test1457 test1458 test1459 test1460 test1461 test1462 test1463 \
-test1464 test1465 test1466 test1467 test1468 \
+test1464 test1465 test1466 test1467 test1468 test1469 \
 \
 test1500 test1501 test1502 test1503 test1504 test1505 test1506 test1507 \
 test1508 test1509 test1510 test1511 test1512 test1513 test1514 test1515 \
diff --git a/tests/data/test1469 b/tests/data/test1469
new file mode 100644 (file)
index 0000000..5161c39
--- /dev/null
@@ -0,0 +1,30 @@
+<testcase>
+<info>
+<keywords>
+FTP
+URL
+FAILURE
+</keywords>
+</info>
+
+# Client-side
+<client>
+<server>
+none
+</server>
+ <name>
+Space in FTP upload URL
+ </name>
+ <command>
+"ftp://%HOSTIP:%NOLISTENPORT/%TESTNUMBER%/with space/" -T log/irrelevant-file
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+# 3 == CURLE_URL_MALFORMAT
+<errorcode>
+3
+</errorcode>
+</verify>
+</testcase>