]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
urlapi: provide more detailed return codes 8049/head
authorDaniel Stenberg <daniel@haxx.se>
Tue, 23 Nov 2021 16:07:31 +0000 (17:07 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Thu, 25 Nov 2021 07:36:04 +0000 (08:36 +0100)
Previously, the return code CURLUE_MALFORMED_INPUT was used for almost
30 different URL format violations. This made it hard for users to
understand why a particular URL was not acceptable. Since the API cannot
point out a specific position within the URL for the problem, this now
instead introduces a number of additional and more fine-grained error
codes to allow the API to return more exactly in what "part" or section
of the URL a problem was detected.

Also bug-fixes curl_url_get() with CURLUPART_ZONEID, which previously
returned CURLUE_OK even if no zoneid existed.

Test cases in 1560 have been adjusted and extended. Tests 1538 and 1559
have been updated.

Updated libcurl-errors.3 and curl_url_strerror() accordingly.

Closes #8049

docs/libcurl/libcurl-errors.3
docs/libcurl/symbols-in-versions
include/curl/urlapi.h
lib/strerror.c
lib/urlapi.c
tests/data/test1538
tests/data/test1559
tests/libtest/lib1560.c

index b124e447c7f5da59aa0890cc657706b15885597e..4b4d24fd7d0ef301d5aeccdaa000523e38344051 100644 (file)
@@ -20,7 +20,7 @@
 .\" *
 .\" **************************************************************************
 .\"
-.TH libcurl-errors 3 "1 Jan 2010" "libcurl 7.20.0" "libcurl errors"
+.TH libcurl-errors 3 "23 Nov 2021" "libcurl 7.81.0" "libcurl errors"
 .SH NAME
 libcurl-errors \- error codes in libcurl
 .SH DESCRIPTION
@@ -361,6 +361,30 @@ There is no port part in the URL.
 There is no query part in the URL.
 .IP "CURLUE_NO_FRAGMENT (17)"
 There is no fragment part in the URL.
+.IP "CURLUE_NO_ZONEID (18)"
+There is no zoneid set in the URL.
+.IP "CURLUE_BAD_FILE_URL (19)"
+The file:// URL is invalid.
+.IP "CURLUE_BAD_FRAGMENT (20)"
+The fragment part of the URL contained bad or invalid characters.
+.IP "CURLUE_BAD_HOSTNAME (21)"
+The hostname contained bad or invalid characters.
+.IP "CURLUE_BAD_IPV6 (22)"
+The IPv6 address hostname contained bad or invalid characters.
+.IP "CURLUE_BAD_LOGIN (23)"
+The login part of the URL contained bad or invalid characters.
+.IP "CURLUE_BAD_PASSWORD (24)"
+The password part of the URL contained bad or invalid characters.
+.IP "CURLUE_BAD_PATH (25)"
+The path part of the URL contained bad or invalid characters.
+.IP "CURLUE_BAD_QUERY (26)"
+The query part of the URL contained bad or invalid characters.
+.IP "CURLUE_BAD_SCHEME (27)"
+The scheme part of the URL contained bad or invalid characters.
+.IP "CURLUE_BAD_SLASHES (28)"
+The URL contained an invalid number of slashes.
+.IP "CURLUE_BAD_USER (29)"
+The user part of the URL contained bad or invalid characters.
 .SH "SEE ALSO"
 .BR curl_easy_strerror "(3), " curl_multi_strerror "(3), "
 .BR curl_share_strerror "(3), " curl_url_strerror "(3), "
index 791834d6e6cf69253297c27465be99f1d6424fd1..feec675fefb5f1639aad54fbf4da5382d4079416 100644 (file)
@@ -838,9 +838,20 @@ CURLSSLSET_UNKNOWN_BACKEND      7.56.0
 CURLSTS_DONE                    7.74.0
 CURLSTS_FAIL                    7.74.0
 CURLSTS_OK                      7.74.0
+CURLUE_BAD_FILE_URL             7.81.0
+CURLUE_BAD_FRAGMENT             7.81.0
 CURLUE_BAD_HANDLE               7.62.0
+CURLUE_BAD_HOSTNAME             7.81.0
+CURLUE_BAD_IPV6                 7.81.0
+CURLUE_BAD_LOGIN                7.81.0
 CURLUE_BAD_PARTPOINTER          7.62.0
+CURLUE_BAD_PASSWORD             7.81.0
+CURLUE_BAD_PATH                 7.81.0
 CURLUE_BAD_PORT_NUMBER          7.62.0
+CURLUE_BAD_QUERY                7.81.0
+CURLUE_BAD_SCHEME               7.81.0
+CURLUE_BAD_SLASHES              7.81.0
+CURLUE_BAD_USER                 7.81.0
 CURLUE_MALFORMED_INPUT          7.62.0
 CURLUE_NO_FRAGMENT              7.62.0
 CURLUE_NO_HOST                  7.62.0
@@ -850,6 +861,7 @@ CURLUE_NO_PORT                  7.62.0
 CURLUE_NO_QUERY                 7.62.0
 CURLUE_NO_SCHEME                7.62.0
 CURLUE_NO_USER                  7.62.0
+CURLUE_NO_ZONEID                7.81.0
 CURLUE_OK                       7.62.0
 CURLUE_OUT_OF_MEMORY            7.62.0
 CURLUE_UNKNOWN_PART             7.62.0
index 3c4b4e18aabdbf2fd1acc37b76cd817c3f2953fe..a475f91b60eb206dffdf0e2fa2f3faeb67747305 100644 (file)
@@ -48,6 +48,18 @@ typedef enum {
   CURLUE_NO_PORT,             /* 15 */
   CURLUE_NO_QUERY,            /* 16 */
   CURLUE_NO_FRAGMENT,         /* 17 */
+  CURLUE_NO_ZONEID,           /* 18 */
+  CURLUE_BAD_FILE_URL,        /* 19 */
+  CURLUE_BAD_FRAGMENT,        /* 20 */
+  CURLUE_BAD_HOSTNAME,        /* 21 */
+  CURLUE_BAD_IPV6,            /* 22 */
+  CURLUE_BAD_LOGIN,           /* 23 */
+  CURLUE_BAD_PASSWORD,        /* 24 */
+  CURLUE_BAD_PATH,            /* 25 */
+  CURLUE_BAD_QUERY,           /* 26 */
+  CURLUE_BAD_SCHEME,          /* 27 */
+  CURLUE_BAD_SLASHES,         /* 28 */
+  CURLUE_BAD_USER,            /* 29 */
   CURLUE_LAST
 } CURLUcode;
 
index 31eb2bf790c228e528db530576f2732ed88f6ad8..b8ab0abbc3be738a3b7e65a0cff252eb2b576b6f 100644 (file)
@@ -468,10 +468,10 @@ curl_url_strerror(CURLUcode error)
     return "An invalid 'part' argument was passed as argument";
 
   case CURLUE_MALFORMED_INPUT:
-    return "A malformed input was passed to a URL API function";
+    return "Malformed input to a URL function";
 
   case CURLUE_BAD_PORT_NUMBER:
-    return "The port number was not a decimal number between 0 and 65535";
+    return "Port number was not a decimal number between 0 and 65535";
 
   case CURLUE_UNSUPPORTED_SCHEME:
     return "This libcurl build doesn't support the given URL scheme";
@@ -489,28 +489,64 @@ curl_url_strerror(CURLUcode error)
     return "An unknown part ID was passed to a URL API function";
 
   case CURLUE_NO_SCHEME:
-    return "There is no scheme part in the URL";
+    return "No scheme part in the URL";
 
   case CURLUE_NO_USER:
-    return "There is no user part in the URL";
+    return "No user part in the URL";
 
   case CURLUE_NO_PASSWORD:
-    return "There is no password part in the URL";
+    return "No password part in the URL";
 
   case CURLUE_NO_OPTIONS:
-    return "There is no options part in the URL";
+    return "No options part in the URL";
 
   case CURLUE_NO_HOST:
-    return "There is no host part in the URL";
+    return "No host part in the URL";
 
   case CURLUE_NO_PORT:
-    return "There is no port part in the URL";
+    return "No port part in the URL";
 
   case CURLUE_NO_QUERY:
-    return "There is no query part in the URL";
+    return "No query part in the URL";
 
   case CURLUE_NO_FRAGMENT:
-    return "There is no fragment part in the URL";
+    return "No fragment part in the URL";
+
+  case CURLUE_NO_ZONEID:
+    return "No zoneid part in the URL";
+
+  case CURLUE_BAD_LOGIN:
+    return "Bad login part";
+
+  case CURLUE_BAD_IPV6:
+    return "Bad IPv6 address";
+
+  case CURLUE_BAD_HOSTNAME:
+    return "Bad hostname";
+
+  case CURLUE_BAD_FILE_URL:
+    return "Bad file:// URL";
+
+  case CURLUE_BAD_SLASHES:
+    return "Unsupported number of slashes";
+
+  case CURLUE_BAD_SCHEME:
+    return "Bad scheme";
+
+  case CURLUE_BAD_PATH:
+    return "Bad path";
+
+  case CURLUE_BAD_FRAGMENT:
+    return "Bad fragment";
+
+  case CURLUE_BAD_QUERY:
+    return "Bad query";
+
+  case CURLUE_BAD_PASSWORD:
+    return "Bad password";
+
+  case CURLUE_BAD_USER:
+    return "Bad user";
 
   case CURLUE_LAST:
     break;
index 6963a805bb4c5254edbcb201dd7edfd9d167ac35..372ffe50a72c80d1beb1bd91bd3c3780970f005b 100644 (file)
@@ -428,6 +428,29 @@ static char *concat_url(const char *base, const char *relurl)
   return newest;
 }
 
+/* scan for byte values < 31 or 127 */
+static bool junkscan(const char *part, unsigned int flags)
+{
+  if(part) {
+    static const char badbytes[]={
+      /* */ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+      0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+      0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+      0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+      0x7f, 0x00 /* null-terminate */
+    };
+    size_t n = strlen(part);
+    size_t nfine = strcspn(part, badbytes);
+    if(nfine != n)
+      /* since we don't know which part is scanned, return a generic error
+         code */
+      return TRUE;
+    if(!(flags & CURLU_ALLOW_SPACE) && strchr(part, ' '))
+      return TRUE;
+  }
+  return FALSE;
+}
+
 /*
  * parse_hostname_login()
  *
@@ -475,7 +498,7 @@ static CURLUcode parse_hostname_login(struct Curl_URL *u,
                                    (h && (h->flags & PROTOPT_URLOPTIONS)) ?
                                    &optionsp:NULL);
   if(ccode) {
-    result = CURLUE_MALFORMED_INPUT;
+    result = CURLUE_BAD_LOGIN;
     goto out;
   }
 
@@ -485,15 +508,28 @@ static CURLUcode parse_hostname_login(struct Curl_URL *u,
       result = CURLUE_USER_NOT_ALLOWED;
       goto out;
     }
-
+    if(junkscan(userp, flags)) {
+      result = CURLUE_BAD_USER;
+      goto out;
+    }
     u->user = userp;
   }
 
-  if(passwdp)
+  if(passwdp) {
+    if(junkscan(passwdp, flags)) {
+      result = CURLUE_BAD_PASSWORD;
+      goto out;
+    }
     u->password = passwdp;
+  }
 
-  if(optionsp)
+  if(optionsp) {
+    if(junkscan(optionsp, flags)) {
+      result = CURLUE_BAD_LOGIN;
+      goto out;
+    }
     u->options = optionsp;
+  }
 
   return CURLUE_OK;
   out:
@@ -501,6 +537,9 @@ static CURLUcode parse_hostname_login(struct Curl_URL *u,
   free(userp);
   free(passwdp);
   free(optionsp);
+  u->user = NULL;
+  u->password = NULL;
+  u->options = NULL;
 
   return result;
 }
@@ -524,19 +563,19 @@ UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, char *hostname,
       int zonelen = len;
       if(1 == sscanf(hostname + zonelen, "%*[^]]%c%n", &endbracket, &len)) {
         if(']' != endbracket)
-          return CURLUE_MALFORMED_INPUT;
+          return CURLUE_BAD_IPV6;
         portptr = &hostname[--zonelen + len + 1];
       }
       else
-        return CURLUE_MALFORMED_INPUT;
+        return CURLUE_BAD_IPV6;
     }
     else
-      return CURLUE_MALFORMED_INPUT;
+      return CURLUE_BAD_IPV6;
 
     /* this is a RFC2732-style specified IP-address */
     if(portptr && *portptr) {
       if(*portptr != ':')
-        return CURLUE_MALFORMED_INPUT;
+        return CURLUE_BAD_IPV6;
     }
     else
       portptr = NULL;
@@ -587,29 +626,6 @@ UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, char *hostname,
   return CURLUE_OK;
 }
 
-/* scan for byte values < 31 or 127 */
-static bool junkscan(const char *part, unsigned int flags)
-{
-  if(part) {
-    static const char badbytes[]={
-      /* */ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-      0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-      0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-      0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
-      0x7f, 0x00 /* null-terminate */
-    };
-    size_t n = strlen(part);
-    size_t nfine = strcspn(part, badbytes);
-    if(nfine != n)
-      /* since we don't know which part is scanned, return a generic error
-         code */
-      return TRUE;
-    if(!(flags & CURLU_ALLOW_SPACE) && strchr(part, ' '))
-      return TRUE;
-  }
-  return FALSE;
-}
-
 static CURLUcode hostname_check(struct Curl_URL *u, char *hostname)
 {
   size_t len;
@@ -621,12 +637,12 @@ static CURLUcode hostname_check(struct Curl_URL *u, char *hostname)
 #endif
     const char *l = "0123456789abcdefABCDEF:.";
     if(hlen < 4) /* '[::]' is the shortest possible valid string */
-      return CURLUE_MALFORMED_INPUT;
+      return CURLUE_BAD_IPV6;
     hostname++;
     hlen -= 2;
 
     if(hostname[hlen] != ']')
-      return CURLUE_MALFORMED_INPUT;
+      return CURLUE_BAD_IPV6;
 
     /* only valid letters are ok */
     len = strspn(hostname, l);
@@ -643,6 +659,7 @@ static CURLUcode hostname_check(struct Curl_URL *u, char *hostname)
         while(*h && (*h != ']') && (i < 15))
           zoneid[i++] = *h++;
         if(!i || (']' != *h))
+          /* impossible to reach? */
           return CURLUE_MALFORMED_INPUT;
         zoneid[i] = 0;
         u->zoneid = strdup(zoneid);
@@ -652,13 +669,13 @@ static CURLUcode hostname_check(struct Curl_URL *u, char *hostname)
         hostname[len + 1] = 0; /* terminate the hostname */
       }
       else
-        return CURLUE_MALFORMED_INPUT;
+        return CURLUE_BAD_IPV6;
       /* hostname is fine */
     }
 #ifdef ENABLE_IPV6
     hostname[hlen] = 0; /* end the address there */
     if(1 != Curl_inet_pton(AF_INET6, hostname, dest))
-      return CURLUE_MALFORMED_INPUT;
+      return CURLUE_BAD_IPV6;
     hostname[hlen] = ']'; /* restore ending bracket */
 #endif
   }
@@ -667,7 +684,7 @@ static CURLUcode hostname_check(struct Curl_URL *u, char *hostname)
     len = strcspn(hostname, " \r\n");
     if(hlen != len)
       /* hostname with bad content */
-      return CURLUE_MALFORMED_INPUT;
+      return CURLUE_BAD_HOSTNAME;
   }
   if(!hostname[0])
     return CURLUE_NO_HOST;
@@ -782,7 +799,7 @@ static CURLUcode decode_host(char *hostname, char **outp)
     CURLcode result = Curl_urldecode(NULL, hostname, 0,
                                      outp, &dlen, REJECT_CTRL);
     if(result)
-      return CURLUE_MALFORMED_INPUT;
+      return CURLUE_BAD_HOSTNAME;
   }
 
   return CURLUE_OK;
@@ -830,7 +847,7 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
   if(url_has_scheme && !strcmp(schemebuf, "file")) {
     if(urllen <= 6)
       /* file:/ is not enough to actually be a complete file: URL */
-      return CURLUE_MALFORMED_INPUT;
+      return CURLUE_BAD_FILE_URL;
 
     /* path has been allocated large enough to hold this */
     strcpy(path, &url[5]);
@@ -884,7 +901,7 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
              host name */
           path = strpbrk(ptr, "/\\:*?\"<>|");
           if(!path || *path != '/')
-            return CURLUE_MALFORMED_INPUT;
+            return CURLUE_BAD_FILE_URL;
 
           len = path - ptr;
           if(len) {
@@ -897,7 +914,7 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
 #else
           /* Invalid file://hostname/, expected localhost or 127.0.0.1 or
              none */
-          return CURLUE_MALFORMED_INPUT;
+          return CURLUE_BAD_FILE_URL;
 #endif
         }
       }
@@ -914,7 +931,7 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
     if(('/' == path[0] && STARTS_WITH_URL_DRIVE_PREFIX(&path[1])) ||
        STARTS_WITH_URL_DRIVE_PREFIX(path)) {
       /* File drive letters are only accepted in MSDOS/Windows */
-      return CURLUE_MALFORMED_INPUT;
+      return CURLUE_BAD_FILE_URL;
     }
 #else
     /* If the path starts with a slash and a drive letter, ditch the slash */
@@ -941,7 +958,7 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
       }
       if((i < 1) || (i>3))
         /* less than one or more than three slashes */
-        return CURLUE_MALFORMED_INPUT;
+        return CURLUE_BAD_SLASHES;
 
       schemep = schemebuf;
       if(!Curl_builtin_scheme(schemep) &&
@@ -949,13 +966,13 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
         return CURLUE_UNSUPPORTED_SCHEME;
 
       if(junkscan(schemep, flags))
-        return CURLUE_MALFORMED_INPUT;
+        return CURLUE_BAD_SCHEME;
     }
     else {
       /* no scheme! */
 
       if(!(flags & (CURLU_DEFAULT_SCHEME|CURLU_GUESS_SCHEME)))
-        return CURLUE_MALFORMED_INPUT;
+        return CURLUE_BAD_SCHEME;
       if(flags & CURLU_DEFAULT_SCHEME)
         schemep = DEFAULT_SCHEME;
 
@@ -966,7 +983,8 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
     }
     hostp = p; /* host name starts here */
 
-    while(*p && !HOSTNAME_END(*p)) /* find end of host name */
+    /* find the end of the host name + port number */
+    while(*p && !HOSTNAME_END(*p))
       p++;
 
     len = p - hostp;
@@ -976,7 +994,7 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
     }
     else {
       if(!(flags & CURLU_NO_AUTHORITY))
-        return CURLUE_MALFORMED_INPUT;
+        return CURLUE_NO_HOST;
     }
 
     len = strlen(p);
@@ -990,9 +1008,6 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
     }
   }
 
-  if(junkscan(path, flags))
-    return CURLUE_MALFORMED_INPUT;
-
   if((flags & CURLU_URLENCODE) && path[0]) {
     /* worst case output length is 3x the original! */
     char *newp = malloc(strlen(path) * 3);
@@ -1006,6 +1021,8 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
   fragment = strchr(path, '#');
   if(fragment) {
     *fragment++ = 0;
+    if(junkscan(fragment, flags))
+      return CURLUE_BAD_FRAGMENT;
     if(fragment[0]) {
       u->fragment = strdup(fragment);
       if(!u->fragment)
@@ -1016,12 +1033,17 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
   query = strchr(path, '?');
   if(query) {
     *query++ = 0;
+    if(junkscan(query, flags))
+      return CURLUE_BAD_QUERY;
     /* done even if the query part is a blank string */
     u->query = strdup(query);
     if(!u->query)
       return CURLUE_OUT_OF_MEMORY;
   }
 
+  if(junkscan(path, flags))
+    return CURLUE_BAD_PATH;
+
   if(!path[0])
     /* if there's no path left set, unset */
     path = NULL;
@@ -1051,12 +1073,10 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
 
   if(hostname) {
     char normalized_ipv4[sizeof("255.255.255.255") + 1];
+
     /*
      * Parse the login details and strip them out of the host name.
      */
-    if(junkscan(hostname, flags))
-      return CURLUE_MALFORMED_INPUT;
-
     result = parse_hostname_login(u, &hostname, flags);
     if(result)
       return result;
@@ -1065,6 +1085,9 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
     if(result)
       return result;
 
+    if(junkscan(hostname, flags))
+      return CURLUE_BAD_HOSTNAME;
+
     if(0 == strlen(hostname) && (flags & CURLU_NO_AUTHORITY)) {
       /* Skip hostname check, it's allowed to be empty. */
       u->host = strdup("");
@@ -1210,6 +1233,7 @@ CURLUcode curl_url_get(CURLU *u, CURLUPart what,
     break;
   case CURLUPART_ZONEID:
     ptr = u->zoneid;
+    ifmissing = CURLUE_NO_ZONEID;
     break;
   case CURLUPART_PORT:
     ptr = u->port;
@@ -1467,7 +1491,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
   case CURLUPART_SCHEME:
     if(strlen(part) > MAX_SCHEME_LEN)
       /* too long */
-      return CURLUE_MALFORMED_INPUT;
+      return CURLUE_BAD_SCHEME;
     if(!(flags & CURLU_NON_SUPPORT_SCHEME) &&
        /* verify that it is a fine scheme */
        !Curl_builtin_scheme(part))
@@ -1488,7 +1512,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
     size_t len = strcspn(part, " \r\n");
     if(strlen(part) != len)
       /* hostname with bad content */
-      return CURLUE_MALFORMED_INPUT;
+      return CURLUE_BAD_HOSTNAME;
     storep = &u->host;
     Curl_safefree(u->zoneid);
     break;
@@ -1505,7 +1529,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
       return CURLUE_BAD_PORT_NUMBER;
     if(*endp)
       /* weirdly provided number, not good! */
-      return CURLUE_MALFORMED_INPUT;
+      return CURLUE_BAD_PORT_NUMBER;
     storep = &u->port;
   }
   break;
@@ -1669,7 +1693,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
       else {
         if(hostname_check(u, (char *)newp)) {
           free((char *)newp);
-          return CURLUE_MALFORMED_INPUT;
+          return CURLUE_BAD_HOSTNAME;
         }
       }
     }
index 1e5287fe15841be32dab75cf0cfced4d291c364d..06810d42aba26a71cd879b479fce6ccaad9e342e 100644 (file)
@@ -155,22 +155,34 @@ s6: CURLSHcode unknown
 u0: No error
 u1: An invalid CURLU pointer was passed as argument
 u2: An invalid 'part' argument was passed as argument
-u3: A malformed input was passed to a URL API function
-u4: The port number was not a decimal number between 0 and 65535
+u3: Malformed input to a URL function
+u4: Port number was not a decimal number between 0 and 65535
 u5: This libcurl build doesn't support the given URL scheme
 u6: URL decode error, most likely because of rubbish in the input
 u7: A memory function failed
 u8: Credentials was passed in the URL when prohibited
 u9: An unknown part ID was passed to a URL API function
-u10: There is no scheme part in the URL
-u11: There is no user part in the URL
-u12: There is no password part in the URL
-u13: There is no options part in the URL
-u14: There is no host part in the URL
-u15: There is no port part in the URL
-u16: There is no query part in the URL
-u17: There is no fragment part in the URL
-u18: CURLUcode unknown
+u10: No scheme part in the URL
+u11: No user part in the URL
+u12: No password part in the URL
+u13: No options part in the URL
+u14: No host part in the URL
+u15: No port part in the URL
+u16: No query part in the URL
+u17: No fragment part in the URL
+u18: No zoneid part in the URL
+u19: Bad file:// URL
+u20: Bad fragment
+u21: Bad hostname
+u22: Bad IPv6 address
+u23: Bad login part
+u24: Bad password
+u25: Bad path
+u26: Bad query
+u27: Bad scheme
+u28: Unsupported number of slashes
+u29: Bad user
+u30: CURLUcode unknown
 </stdout>
 </verify>
 
index 6366afb51824c3710d35f4090342daef60e66458..e62b073f4bed31928a609cbf6d9d832d50b14fdd 100644 (file)
@@ -35,9 +35,9 @@ Set excessive URL lengths
 <stdout>
 CURLOPT_URL 10000000 bytes URL == 43
 CURLOPT_POSTFIELDS 10000000 bytes data == 0
-CURLUPART_URL 10000000 bytes URL == 3 (A malformed input was passed to a URL API function)
-CURLUPART_SCHEME 10000000 bytes scheme == 3 (A malformed input was passed to a URL API function)
-CURLUPART_USER 10000000 bytes user == 3 (A malformed input was passed to a URL API function)
+CURLUPART_URL 10000000 bytes URL == 3 (Malformed input to a URL function)
+CURLUPART_SCHEME 10000000 bytes scheme == 27 (Bad scheme)
+CURLUPART_USER 10000000 bytes user == 3 (Malformed input to a URL function)
 </stdout>
 </verify>
 
index 1cc1a60ec8be63b76ec43c0433ab137482712396..f09454c451daac0ee3cc49d49638abba718b2714 100644 (file)
@@ -129,17 +129,21 @@ struct querycase {
 };
 
 static const struct testcase get_parts_list[] ={
+  {"https://user:password@example.net/get?this=and#but frag then", "",
+   CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_FRAGMENT},
   {"https://user:password@example.net/get?this=and what", "",
-   CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
+   CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_QUERY},
   {"https://user:password@example.net/ge t?this=and-what", "",
-   CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
+   CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_PATH},
   {"https://user:pass word@example.net/get?this=and-what", "",
-   CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
+   CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_PASSWORD},
   {"https://u ser:password@example.net/get?this=and-what", "",
-   CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
+   CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_USER},
+  {"imap://user:pass;opt ion@server/path", "",
+   CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_LOGIN},
   /* no space allowed in scheme */
   {"htt ps://user:password@example.net/get?this=and-what", "",
-   CURLU_NON_SUPPORT_SCHEME|CURLU_ALLOW_SPACE, 0, CURLUE_MALFORMED_INPUT},
+   CURLU_NON_SUPPORT_SCHEME|CURLU_ALLOW_SPACE, 0, CURLUE_BAD_SCHEME},
   {"https://user:password@example.net/get?this=and what",
    "https | user | password | [13] | example.net | [15] | /get | "
    "this=and what | [17]",
@@ -213,9 +217,9 @@ static const struct testcase get_parts_list[] ={
    "com/color/?green#no-red",
    CURLU_DEFAULT_SCHEME, 0, CURLUE_OK },
   {"http://[ab.be:1]/x", "",
-   CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
+   CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_IPV6},
   {"http://[ab.be]/x", "",
-   CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
+   CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_IPV6},
   /* URL without host name */
   {"http://a:b@/x", "",
    CURLU_DEFAULT_SCHEME, 0, CURLUE_NO_HOST},
@@ -254,7 +258,7 @@ static const struct testcase get_parts_list[] ={
    0, 0, CURLUE_OK},
   {"file://hello.html",
    "",
-   0, 0, CURLUE_MALFORMED_INPUT},
+   0, 0, CURLUE_BAD_FILE_URL},
   {"http://HO0_-st/",
    "http | [11] | [12] | [13] | HO0_-st | [15] | / | [16] | [17]",
    0, 0, CURLUE_OK},
@@ -272,7 +276,7 @@ static const struct testcase get_parts_list[] ={
    0, 0, CURLUE_OK},
   {"file:/",
    "file | [11] | [12] | [13] | [14] | [15] | | [16] | [17]",
-   0, 0, CURLUE_MALFORMED_INPUT},
+   0, 0, CURLUE_BAD_FILE_URL},
   {"file://127.0.0.1/hello.html",
    "file | [11] | [12] | [13] | [14] | [15] | /hello.html | [16] | [17]",
    0, 0, CURLUE_OK},
@@ -295,9 +299,9 @@ static const struct testcase get_parts_list[] ={
    "https | [11] | [12] | [13] | 127abc.com | [15] | / | [16] | [17]",
    CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
   {"https:// example.com?check", "",
-   CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
+   CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_HOSTNAME},
   {"https://e x a m p l e.com?check", "",
-   CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
+   CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_HOSTNAME},
   {"https://example.com?check",
    "https | [11] | [12] | [13] | example.com | [15] | / | check | [17]",
    CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
@@ -357,7 +361,7 @@ static const struct testcase get_parts_list[] ={
    CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
   {"http:////user:password@example.com:1234/path/html?query=name#anchor",
    "",
-   CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
+   CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_SLASHES},
   {NULL, NULL, 0, 0, CURLUE_OK},
 };
 
@@ -367,8 +371,8 @@ static const struct urltestcase get_url_list[] = {
   {"https://h%c", "https://h%25c/", 0, 0, CURLUE_OK},
   {"https://%%%%%%", "https://%25%25%25%25%25%25/", 0, 0, CURLUE_OK},
   {"https://%41", "https://A/", 0, 0, CURLUE_OK},
-  {"https://%20", "", 0, 0, CURLUE_MALFORMED_INPUT},
-  {"https://%41%0d", "", 0, 0, CURLUE_MALFORMED_INPUT},
+  {"https://%20", "", 0, 0, CURLUE_BAD_HOSTNAME},
+  {"https://%41%0d", "", 0, 0, CURLUE_BAD_HOSTNAME},
   {"https://%25", "https://%25/", 0, 0, CURLUE_OK},
   {"https://_%c0_", "https://_\xC0_/", 0, 0, CURLUE_OK},
   {"https://_%c0_", "https://_%C0_/", 0, CURLU_URLENCODE, CURLUE_OK},
@@ -385,7 +389,7 @@ static const struct urltestcase get_url_list[] = {
   {"https://+127.0.0.1", "https://%2B127.0.0.1/", 0, CURLU_URLENCODE,
    CURLUE_OK},
   {"https://127.-0.0.1", "https://127.-0.0.1/", 0, 0, CURLUE_OK},
-  {"https://127.0. 1", "https://127.0.0.1/", 0, 0, CURLUE_MALFORMED_INPUT},
+  {"https://127.0. 1", "https://127.0.0.1/", 0, 0, CURLUE_BAD_HOSTNAME},
   {"https://1.0x1000000", "https://1.0x1000000/", 0, 0, CURLUE_OK},
   {"https://1.2.3.256", "https://1.2.3.256/", 0, 0, CURLUE_OK},
   {"https://1.2.3.4.5", "https://1.2.3.4.5/", 0, 0, CURLUE_OK},
@@ -398,10 +402,10 @@ static const struct urltestcase get_url_list[] = {
   /* 41 bytes scheme is not allowed */
   {"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA://hostname/path",
    "",
-   CURLU_NON_SUPPORT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
+   CURLU_NON_SUPPORT_SCHEME, 0, CURLUE_BAD_SCHEME},
   {"https://[fe80::20c:29ff:fe9c:409b%]:1234",
    "",
-   0, 0, CURLUE_MALFORMED_INPUT},
+   0, 0, CURLUE_BAD_IPV6},
   {"https://[fe80::20c:29ff:fe9c:409b%25]:1234",
    "https://[fe80::20c:29ff:fe9c:409b%2525]:1234/",
    0, 0, CURLUE_OK},
@@ -437,14 +441,14 @@ static const struct urltestcase get_url_list[] = {
    CURLU_GUESS_SCHEME, 0, CURLUE_OK},
   {"HTTP://test/", "http://test/", 0, 0, CURLUE_OK},
   {"http://HO0_-st..~./", "http://HO0_-st..~./", 0, 0, CURLUE_OK},
-  {"http:/@example.com: 123/", "", 0, 0, CURLUE_MALFORMED_INPUT},
-  {"http:/@example.com:123 /", "", 0, 0, CURLUE_MALFORMED_INPUT},
+  {"http:/@example.com: 123/", "", 0, 0, CURLUE_BAD_PORT_NUMBER},
+  {"http:/@example.com:123 /", "", 0, 0, CURLUE_BAD_PORT_NUMBER},
   {"http:/@example.com:123a/", "", 0, 0, CURLUE_BAD_PORT_NUMBER},
-  {"http://host/file\r", "", 0, 0, CURLUE_MALFORMED_INPUT},
-  {"http://host/file\n\x03", "", 0, 0, CURLUE_MALFORMED_INPUT},
+  {"http://host/file\r", "", 0, 0, CURLUE_BAD_PATH},
+  {"http://host/file\n\x03", "", 0, 0, CURLUE_BAD_PATH},
   {"htt\x02://host/file", "",
-   CURLU_NON_SUPPORT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
-  {" http://host/file", "", 0, 0, CURLUE_MALFORMED_INPUT},
+   CURLU_NON_SUPPORT_SCHEME, 0, CURLUE_BAD_SCHEME},
+  {" http://host/file", "", 0, 0, CURLUE_BAD_SCHEME},
   /* here the password ends at the semicolon and options is 'word' */
   {"imap://user:pass;word@host/file",
    "imap://user:pass;word@host/file",
@@ -464,7 +468,7 @@ static const struct urltestcase get_url_list[] = {
    0, 0, CURLUE_OK},
   {"file:./",
    "file://",
-   0, 0, CURLUE_MALFORMED_INPUT},
+   0, 0, CURLUE_BAD_SCHEME},
   {"http://example.com/hello/../here",
    "http://example.com/hello/../here",
    CURLU_PATH_AS_IS, 0, CURLUE_OK},
@@ -500,7 +504,7 @@ static const struct urltestcase get_url_list[] = {
    CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
   {"example.com/path/html",
    "",
-   0, 0, CURLUE_MALFORMED_INPUT},
+   0, 0, CURLUE_BAD_SCHEME},
   {"http://user:password@example.com:1234/path/html?query=name#anchor",
    "http://user:password@example.com:1234/path/html?query=name#anchor",
    0, 0, CURLUE_OK},
@@ -524,7 +528,7 @@ static const struct urltestcase get_url_list[] = {
    CURLU_NON_SUPPORT_SCHEME, 0, CURLUE_OK},
   {"custom-scheme://?expected=test-bad",
    "",
-   CURLU_NON_SUPPORT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
+   CURLU_NON_SUPPORT_SCHEME, 0, CURLUE_NO_HOST},
   {"custom-scheme://?expected=test-new-good",
    "custom-scheme:///?expected=test-new-good",
    CURLU_NON_SUPPORT_SCHEME | CURLU_NO_AUTHORITY, 0, CURLUE_OK},
@@ -565,7 +569,7 @@ static const struct setcase set_parts_list[] = {
    /* Set a 41 bytes scheme. That's too long so the old scheme remains set. */
    "scheme=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbc,",
    "https://example.com/",
-   0, CURLU_NON_SUPPORT_SCHEME, CURLUE_OK, CURLUE_MALFORMED_INPUT},
+   0, CURLU_NON_SUPPORT_SCHEME, CURLUE_OK, CURLUE_BAD_SCHEME},
   {"https://example.com/",
    /* set a 40 bytes scheme */
    "scheme=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,",
@@ -586,7 +590,7 @@ static const struct setcase set_parts_list[] = {
   {"https://host:1234/",
    "port=56 78,",
    "https://host:1234/",
-   0, 0, CURLUE_OK, CURLUE_MALFORMED_INPUT},
+   0, 0, CURLUE_OK, CURLUE_BAD_PORT_NUMBER},
   {"https://host:1234/",
    "port=0,",
    "https://host:1234/",
@@ -619,7 +623,7 @@ static const struct setcase set_parts_list[] = {
   {NULL,
    "scheme=https,host=  ,path= ,user= ,password= ,query= ,fragment= ,",
    "[nothing]",
-   0, CURLU_URLENCODE, CURLUE_OK, CURLUE_MALFORMED_INPUT},
+   0, CURLU_URLENCODE, CURLUE_OK, CURLUE_BAD_HOSTNAME},
   {NULL,
    "scheme=https,host=foobar,path=/this /path /is /here,",
    "https://foobar/this%20/path%20/is%20/here",
@@ -688,7 +692,7 @@ static const struct setcase set_parts_list[] = {
    "host=\"\",",
    "custom-scheme://host/",
    CURLU_NON_SUPPORT_SCHEME, CURLU_NON_SUPPORT_SCHEME, CURLUE_OK,
-   CURLUE_MALFORMED_INPUT},
+   CURLUE_BAD_HOSTNAME},
   {"custom-scheme://host",
    "host=\"\",",
    "custom-scheme:///",
@@ -1164,10 +1168,64 @@ static int scopeid(void)
   return error;
 }
 
+static int get_nothing(void)
+{
+  CURLU *u = curl_url();
+  if(u) {
+    char *p;
+    CURLUcode rc;
+
+    rc = curl_url_get(u, CURLUPART_SCHEME, &p, 0);
+    if(rc != CURLUE_NO_SCHEME)
+      fprintf(stderr, "unexpected return code line %u\n", __LINE__);
+
+    rc = curl_url_get(u, CURLUPART_HOST, &p, 0);
+    if(rc != CURLUE_NO_HOST)
+      fprintf(stderr, "unexpected return code line %u\n", __LINE__);
+
+    rc = curl_url_get(u, CURLUPART_USER, &p, 0);
+    if(rc != CURLUE_NO_USER)
+      fprintf(stderr, "unexpected return code line %u\n", __LINE__);
+
+    rc = curl_url_get(u, CURLUPART_PASSWORD, &p, 0);
+    if(rc != CURLUE_NO_PASSWORD)
+      fprintf(stderr, "unexpected return code line %u\n", __LINE__);
+
+    rc = curl_url_get(u, CURLUPART_OPTIONS, &p, 0);
+    if(rc != CURLUE_NO_OPTIONS)
+      fprintf(stderr, "unexpected return code line %u\n", __LINE__);
+
+    rc = curl_url_get(u, CURLUPART_PATH, &p, 0);
+    if(rc != CURLUE_OK)
+      fprintf(stderr, "unexpected return code line %u\n", __LINE__);
+    else
+      curl_free(p);
+
+    rc = curl_url_get(u, CURLUPART_QUERY, &p, 0);
+    if(rc != CURLUE_NO_QUERY)
+      fprintf(stderr, "unexpected return code line %u\n", __LINE__);
+
+    rc = curl_url_get(u, CURLUPART_FRAGMENT, &p, 0);
+    if(rc != CURLUE_NO_FRAGMENT)
+      fprintf(stderr, "unexpected return code line %u\n", __LINE__);
+
+    rc = curl_url_get(u, CURLUPART_ZONEID, &p, 0);
+    if(rc != CURLUE_OK)
+      fprintf(stderr, "unexpected return code %u on line %u\n", (int)rc,
+              __LINE__);
+
+    curl_url_cleanup(u);
+  }
+  return 0;
+}
+
 int test(char *URL)
 {
   (void)URL; /* not used */
 
+  if(get_nothing())
+    return 7;
+
   if(scopeid())
     return 6;