urlapi: stop extracting hostname from file:// URLs on Windows

There is no reason we should treat this part different on Windows. Noe
anything except blank, localhost or 127.0.0.1 cause error there as well.

Also: fix query handling in urlencode_str

Closes #21296
This commit is contained in:
Daniel Stenberg 2026-04-13 14:55:16 +02:00
parent 0b4ebebb06
commit 9ceb3ff46a
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
3 changed files with 60 additions and 89 deletions

View file

@ -145,35 +145,37 @@ static CURLcode test_unit1675(const char *arg)
struct urlencode_test {
const char *in;
bool relative;
bool query;
unsigned int query;
const char *out;
};
const struct urlencode_test tests[] = {
{"http://leave\x01/hello\x01world", FALSE, FALSE,
{"http://leave\x01/hello\x01world", FALSE, QUERY_NO,
"http://leave\x01/hello%01world"},
{"http://leave/hello\x01world", FALSE, FALSE,
{"http://leave/hello\x01world", FALSE, QUERY_NO,
"http://leave/hello%01world"},
{"http://le ave/hello\x01world", FALSE, FALSE,
{"http://le ave/hello\x01world", FALSE, QUERY_NO,
"http://le ave/hello%01world"},
{"hello\x01world", TRUE, FALSE, "hello%01world"},
{"hello\xf0world", TRUE, FALSE, "hello%F0world"},
{"hello world", TRUE, FALSE, "hello%20world"},
{"hello%20world", TRUE, FALSE, "hello%20world"},
{"hello world", TRUE, TRUE, "hello+world"},
{"a+b c", TRUE, FALSE, "a+b%20c"},
{"a%20b%20c", TRUE, FALSE, "a%20b%20c"},
{"a%aab%aac", TRUE, FALSE, "a%AAb%AAc"},
{"a%aab%AAc", TRUE, FALSE, "a%AAb%AAc"},
{"w%w%x", TRUE, FALSE, "w%w%x"},
{"w%wf%xf", TRUE, FALSE, "w%wf%xf"},
{"w%fw%fw", TRUE, FALSE, "w%fw%fw"},
{"a+b c", TRUE, TRUE, "a+b+c"},
{"/foo/bar", TRUE, FALSE, "/foo/bar"},
{"/foo/bar", TRUE, TRUE, "/foo/bar"},
{"/foo/ bar", TRUE, FALSE, "/foo/%20bar"},
{"/foo/ bar", TRUE, TRUE, "/foo/+bar"},
{"~-._", TRUE, FALSE, "~-._"},
{"~-._", TRUE, TRUE, "~-._"},
{"hello\x01world", TRUE, QUERY_NO, "hello%01world"},
{"hello\xf0world", TRUE, QUERY_NO, "hello%F0world"},
{"hello world", TRUE, QUERY_NO, "hello%20world"},
{"hello%20world", TRUE, QUERY_NO, "hello%20world"},
{"hello world", TRUE, QUERY_YES, "hello+world"},
{"a+b c", TRUE, QUERY_NO, "a+b%20c"},
{"a%20b%20c", TRUE, QUERY_NO, "a%20b%20c"},
{"a%aab%aac", TRUE, QUERY_NO, "a%AAb%AAc"},
{"a%aab%AAc", TRUE, QUERY_NO, "a%AAb%AAc"},
{"w%w%x", TRUE, QUERY_NO, "w%w%x"},
{"w%wf%xf", TRUE, QUERY_NO, "w%wf%xf"},
{"w%fw%fw", TRUE, QUERY_NO, "w%fw%fw"},
{"a+b c", TRUE, QUERY_YES, "a+b+c"},
{"/foo/bar", TRUE, QUERY_NO, "/foo/bar"},
{"/foo/bar", TRUE, QUERY_YES, "/foo/bar"},
{"/foo/ bar", TRUE, QUERY_NO, "/foo/%20bar"},
{"/foo/ bar", TRUE, QUERY_YES, "/foo/+bar"},
{"~-._", TRUE, QUERY_NO, "~-._"},
{"~-._", TRUE, QUERY_YES, "~-._"},
{"foo bar?foo bar", TRUE, QUERY_NO, "foo%20bar?foo%20bar"},
{"foo bar?foo bar", TRUE, QUERY_NOT_YET, "foo%20bar?foo+bar"},
};
curlx_dyn_init(&out, 256);
@ -259,18 +261,16 @@ static CURLcode test_unit1675(const char *arg)
unsigned int i;
struct file_test {
const char *in;
const char *out_host;
const char *out_path;
bool fine;
};
const struct file_test tests[] = {
{"file:///etc/hosts", "", "/etc/hosts", TRUE},
{"file://localhost/etc/hosts", "", "/etc/hosts", TRUE},
{"file://apple/etc/hosts", "", "/etc/hosts", FALSE},
{"file:///etc/hosts", "/etc/hosts", TRUE},
{"file://localhost/etc/hosts", "/etc/hosts", TRUE},
{"file://apple/etc/hosts", "/etc/hosts", FALSE},
#ifdef _WIN32
{"file:///c:/windows/system32", "", "c:/windows/system32", TRUE},
{"file://localhost/c:/windows/system32", "",
"c:/windows/system32", TRUE},
{"file:///c:/windows/system32", "c:/windows/system32", TRUE},
{"file://localhost/c:/windows/system32", "c:/windows/system32", TRUE},
#endif
};
@ -280,28 +280,19 @@ static CURLcode test_unit1675(const char *arg)
if(!u)
return CURLE_OUT_OF_MEMORY;
uc = parse_file(tests[i].in, strlen(tests[i].in), u, &host, &path,
&pathlen);
uc = parse_file(tests[i].in, strlen(tests[i].in), u, &path, &pathlen);
if(!tests[i].fine && !uc) {
curl_mfprintf(stderr, "Unexpectedly fine for input '%s'\n",
tests[i].in);
fails++;
}
else if(tests[i].out_host[0]) {
/* expecting a hostname output */
if(!curlx_dyn_len(&host) ||
strcmp(curlx_dyn_ptr(&host), tests[i].out_host))
error = TRUE;
}
if(tests[i].fine &&
(uc ||
strncmp(path, tests[i].out_path, pathlen) ||
strlen(tests[i].out_path) != pathlen)) {
curl_mfprintf(stderr, "parse_file('%s') failed:"
" expected host '%s', path '%s'; got host '%s',"
" path '%.*s'\n",
tests[i].in, tests[i].out_host, tests[i].out_path,
uc ? "error" : curlx_dyn_ptr(&host),
" expected path '%s'; got path '%.*s'\n",
tests[i].in, tests[i].out_path,
(int)pathlen, path);
fails++;
}