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