Zebediah Figura : kernelbase: Allow usernames and passwords to contain any characters in UrlGetPart().

Alexandre Julliard julliard at winehq.org
Tue Feb 15 16:07:16 CST 2022


Module: wine
Branch: master
Commit: 932daf59c38b83a6baa12ad06bc1258ce52fc1c6
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=932daf59c38b83a6baa12ad06bc1258ce52fc1c6

Author: Zebediah Figura <zfigura at codeweavers.com>
Date:   Mon Feb 14 20:37:09 2022 -0600

kernelbase: Allow usernames and passwords to contain any characters in UrlGetPart().

Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/kernelbase/path.c   | 52 +++++++-----------------------------------------
 dlls/shlwapi/tests/url.c | 27 +++++++++++--------------
 2 files changed, 19 insertions(+), 60 deletions(-)

diff --git a/dlls/kernelbase/path.c b/dlls/kernelbase/path.c
index dfb37006da8..823fb51a68e 100644
--- a/dlls/kernelbase/path.c
+++ b/dlls/kernelbase/path.c
@@ -77,7 +77,6 @@ struct parsed_url
 enum url_scan_type
 {
     SCHEME,
-    USERPASS,
 };
 
 static WCHAR *heap_strdupAtoW(const char *str)
@@ -4175,42 +4174,6 @@ static const WCHAR * scan_url(const WCHAR *start, DWORD *size, enum url_scan_typ
             *size = 0;
         break;
 
-    case USERPASS:
-        for (;;)
-        {
-            if (isalnum(*start) ||
-                    /* user/password only characters */
-                    (*start == ';') ||
-                    (*start == '?') ||
-                    (*start == '&') ||
-                    (*start == '=') ||
-                    /* *extra* characters */
-                    (*start == '!') ||
-                    (*start == '*') ||
-                    (*start == '\'') ||
-                    (*start == '(') ||
-                    (*start == ')') ||
-                    (*start == ',') ||
-                    /* *safe* characters */
-                    (*start == '$') ||
-                    (*start == '_') ||
-                    (*start == '+') ||
-                    (*start == '-') ||
-                    (*start == '.') ||
-                    (*start == ' '))
-            {
-                start++;
-                (*size)++;
-            }
-            else if (*start == '%' && isxdigit(start[1]) && isxdigit(start[2]))
-            {
-                start += 3;
-                *size += 3;
-            }
-            else break;
-        }
-        break;
-
     default:
         FIXME("unknown type %d\n", type);
         return L"";
@@ -4240,13 +4203,13 @@ static LONG parse_url(const WCHAR *url, struct parsed_url *pl)
     if ((*work != '/') || (*(work+1) != '/')) goto SuccessExit;
 
     pl->username = work + 2;
-    work = scan_url(pl->username, &pl->username_len, USERPASS);
-    if (*work == ':' )
+    work = parse_url_element( pl->username, L":@/\\?#" );
+    pl->username_len = work - pl->username;
+    if (*work == ':')
     {
-        /* parse password */
-        work++;
-        pl->password = work;
-        work = scan_url(pl->password, &pl->password_len, USERPASS);
+        pl->password = work + 1;
+        work = parse_url_element( pl->password, L"@/\\?#" );
+        pl->password_len = work - pl->password;
         if (*work != '@')
         {
             /* what we just parsed must be the hostname and port
@@ -4262,14 +4225,13 @@ static LONG parse_url(const WCHAR *url, struct parsed_url *pl)
         pl->password_len = 0;
         pl->password = 0;
     }
-    else if (!*work || *work == '/' || *work == '.')
+    else
     {
         /* what was parsed was hostname, so reset pointers and let it parse */
         pl->username_len = pl->password_len = 0;
         work = pl->username - 1;
         pl->username = pl->password = 0;
     }
-    else goto ErrorExit;
 
     pl->hostname = work + 1;
     work = parse_url_element( pl->hostname, L":/\\?#" );
diff --git a/dlls/shlwapi/tests/url.c b/dlls/shlwapi/tests/url.c
index c4afb1375e9..18ff5021986 100644
--- a/dlls/shlwapi/tests/url.c
+++ b/dlls/shlwapi/tests/url.c
@@ -652,32 +652,32 @@ static void test_UrlGetPart(void)
 
         {"http://host:port:q", URL_PART_HOSTNAME, 0, S_OK, "host"},
         {"http://host:port:q", URL_PART_PORT, 0, S_OK, "port:q"},
-        {"http://user:pass:q@host", URL_PART_USERNAME, 0, S_OK, "user", .todo_hr = TRUE},
-        {"http://user:pass:q@host", URL_PART_PASSWORD, 0, S_OK, "pass:q", .todo_hr = TRUE},
+        {"http://user:pass:q@host", URL_PART_USERNAME, 0, S_OK, "user"},
+        {"http://user:pass:q@host", URL_PART_PASSWORD, 0, S_OK, "pass:q"},
         {"http://user@host@q", URL_PART_USERNAME, 0, S_OK, "user"},
         {"http://user@host@q", URL_PART_HOSTNAME, 0, S_OK, "host at q"},
 
         {"http:localhost/index.html", URL_PART_HOSTNAME, 0, E_FAIL, .todo_hr = TRUE},
         {"http:/localhost/index.html", URL_PART_HOSTNAME, 0, E_FAIL, .todo_hr = TRUE},
 
-        {"http://localhost\\index.html", URL_PART_HOSTNAME, 0, S_OK, "localhost", .todo_hr = TRUE},
+        {"http://localhost\\index.html", URL_PART_HOSTNAME, 0, S_OK, "localhost"},
         {"http:/\\localhost/index.html", URL_PART_HOSTNAME, 0, S_OK, "localhost", .todo_hr = TRUE},
         {"http:\\/localhost/index.html", URL_PART_HOSTNAME, 0, S_OK, "localhost", .todo_hr = TRUE},
 
-        {"ftp://localhost\\index.html", URL_PART_HOSTNAME, 0, S_OK, "localhost", .todo_hr = TRUE},
+        {"ftp://localhost\\index.html", URL_PART_HOSTNAME, 0, S_OK, "localhost"},
         {"ftp:/\\localhost/index.html", URL_PART_HOSTNAME, 0, S_OK, "localhost", .todo_hr = TRUE},
         {"ftp:\\/localhost/index.html", URL_PART_HOSTNAME, 0, S_OK, "localhost", .todo_hr = TRUE},
 
-        {"http://host?a:b@c:d", URL_PART_HOSTNAME, 0, S_OK, "host", .todo_result = TRUE},
+        {"http://host?a:b@c:d", URL_PART_HOSTNAME, 0, S_OK, "host"},
         {"http://host?a:b@c:d", URL_PART_QUERY, 0, S_OK, "a:b at c:d", .todo_hr = TRUE},
-        {"http://host#a:b@c:d", URL_PART_HOSTNAME, 0, S_OK, "host", .todo_hr = TRUE},
+        {"http://host#a:b@c:d", URL_PART_HOSTNAME, 0, S_OK, "host"},
         {"http://host#a:b@c:d", URL_PART_QUERY, 0, S_FALSE, ""},
 
         /* All characters, other than those with special meaning, are allowed. */
         {"http://foo:bar@google.*.com:21/internal.php?query=x&return=y", URL_PART_HOSTNAME, 0, S_OK, "google.*.com"},
-        {"http:// !\"$%&'()*+,-.;<=>[]^_`{|~}\x01\x7f\xff:pass at host", URL_PART_USERNAME, 0, S_OK, " !\"$%&'()*+,-.;<=>[]^_`{|~}\x01\x7f\xff", .todo_hr = TRUE},
-        {"http://user: !\"$%&'()*+,-.;<=>[]^_`{|~}\x01\x7f\xff at host", URL_PART_PASSWORD, 0, S_OK, " !\"$%&'()*+,-.;<=>[]^_`{|~}\x01\x7f\xff", .todo_hr = TRUE},
-        {"http:// !\"$%&'()*+,-.;<=>[]^_`{|~}\x01\x7f\xff", URL_PART_HOSTNAME, 0, S_OK, " !\"$%&'()*+,-.;<=>[]^_`{|~}\x01\x7f\xff", .todo_hr = TRUE},
+        {"http:// !\"$%&'()*+,-.;<=>[]^_`{|~}\x01\x7f\xff:pass at host", URL_PART_USERNAME, 0, S_OK, " !\"$%&'()*+,-.;<=>[]^_`{|~}\x01\x7f\xff"},
+        {"http://user: !\"$%&'()*+,-.;<=>[]^_`{|~}\x01\x7f\xff at host", URL_PART_PASSWORD, 0, S_OK, " !\"$%&'()*+,-.;<=>[]^_`{|~}\x01\x7f\xff"},
+        {"http:// !\"$%&'()*+,-.;<=>[]^_`{|~}\x01\x7f\xff", URL_PART_HOSTNAME, 0, S_OK, " !\"$%&'()*+,-.;<=>[]^_`{|~}\x01\x7f\xff"},
         {"http://host: !\"$%&'()*+,-.;<=>[]^_`{|~}\x01\x7f\xff", URL_PART_PORT, 0, S_OK, " !\"$%&'()*+,-.;<=>[]^_`{|~}\x01\x7f\xff"},
 
         {"http:///index.html", URL_PART_HOSTNAME, 0, S_FALSE, ""},
@@ -837,7 +837,7 @@ static void test_UrlGetPart(void)
         size = 1;
         wcscpy(bufferW, L"x");
         hr = UrlGetPartW(urlW, bufferW, &size, part, flags);
-        todo_wine_if ((tests[i].todo_hr || tests[i].hr == S_FALSE) && !(strchr(url, '"') && part == URL_PART_USERNAME))
+        todo_wine_if (tests[i].todo_hr || tests[i].hr == S_FALSE)
         {
             if (tests[i].hr == S_OK)
                 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
@@ -880,11 +880,8 @@ static void test_UrlGetPart(void)
         }
         else
         {
-            todo_wine_if (strchr(url, '"') && part == URL_PART_USERNAME)
-            {
-                ok(size == ARRAY_SIZE(bufferW), "Got size %u.\n", size);
-                ok(!wcscmp(bufferW, L"x"), "Got result %s.\n", debugstr_w(bufferW));
-            }
+            ok(size == ARRAY_SIZE(bufferW), "Got size %u.\n", size);
+            ok(!wcscmp(bufferW, L"x"), "Got result %s.\n", debugstr_w(bufferW));
         }
 
         winetest_pop_context();




More information about the wine-cvs mailing list