Commit 2c0babee authored by Adam Rice's avatar Adam Rice Committed by Commit Bot

Support IPv6 literals in KURL::SetHostAndPort

KURL::SetHostAndPort would corrupt IPv6 literals because they contain
":" characters. Make it check for "[]" characters and use the first ":"
after an IPv6 address as the start of the port number if one is present.

Fixed: 1012416
Change-Id: If07a671b48c8c1b24b16883fb9072a86b0de7ebc
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1871449Reviewed-by: default avatarKinuko Yasuda <kinuko@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Commit-Queue: Adam Rice <ricea@chromium.org>
Cr-Commit-Position: refs/heads/master@{#710668}
parent 0f83f230
......@@ -476,11 +476,27 @@ static String ParsePortFromStringPosition(const String& value,
}
void KURL::SetHostAndPort(const String& host_and_port) {
wtf_size_t separator = host_and_port.find(':');
if (!separator)
// This method intentionally does very sloppy parsing for backwards
// compatibility. See https://url.spec.whatwg.org/#host-state for what we
// theoretically should be doing.
// This logic for handling IPv6 addresses is adapted from ParseServerInfo in
// //url/third_party/mozilla/url_parse.cc. There's a slight behaviour
// difference for compatibility with the tests: the first colon after the
// address is considered to start the port, instead of the last.
wtf_size_t ipv6_terminator = host_and_port.ReverseFind(']');
if (ipv6_terminator == kNotFound) {
ipv6_terminator =
host_and_port.StartsWith('[') ? host_and_port.length() : 0;
}
wtf_size_t colon = host_and_port.find(':', ipv6_terminator);
if (colon == 0)
return;
if (separator == kNotFound) {
if (colon == kNotFound) {
// |host_and_port| does not include a port, so only overwrite the host.
url::Replacements<char> replacements;
StringUTF8Adaptor host_utf8(host_and_port);
replacements.SetHost(CharactersOrEmpty(host_utf8),
......@@ -489,8 +505,8 @@ void KURL::SetHostAndPort(const String& host_and_port) {
return;
}
String host = host_and_port.Substring(0, separator);
String port = ParsePortFromStringPosition(host_and_port, separator + 1);
String host = host_and_port.Substring(0, colon);
String port = ParsePortFromStringPosition(host_and_port, colon + 1);
StringUTF8Adaptor host_utf8(host);
StringUTF8Adaptor port_utf8(port);
......
......@@ -686,6 +686,17 @@
"port": "2"
}
},
{
"comment": "IPv6 literal address with port, crbug.com/1012416",
"href": "http://example.net",
"new_value": "[2001:db8::2]:4002",
"expected": {
"href": "http://[2001:db8::2]:4002/",
"host": "[2001:db8::2]:4002",
"hostname": "[2001:db8::2]",
"port": "4002"
}
},
{
"comment": "Default port number is removed",
"href": "http://example.net",
......
This is a testharness.js-based test.
Found 592 tests; 299 PASS, 293 FAIL, 0 TIMEOUT, 0 NOTRUN.
Found 595 tests; 305 PASS, 290 FAIL, 0 TIMEOUT, 0 NOTRUN.
PASS Loading data…
PASS URL: Setting <a://example.net>.protocol = '' The empty string is not a valid scheme. Setter leaves the URL unchanged.
PASS <a>: Setting <a://example.net>.protocol = '' The empty string is not a valid scheme. Setter leaves the URL unchanged.
......@@ -232,9 +232,12 @@ FAIL <area>: Setting <a:/foo>.host = 'example.net' Path-only URLs can gain a hos
PASS URL: Setting <http://example.net>.host = '0x7F000001:8080' IPv4 address syntax is normalized
PASS <a>: Setting <http://example.net>.host = '0x7F000001:8080' IPv4 address syntax is normalized
PASS <area>: Setting <http://example.net>.host = '0x7F000001:8080' IPv4 address syntax is normalized
FAIL URL: Setting <http://example.net>.host = '[::0:01]:2' IPv6 address syntax is normalized assert_equals: expected "http://[::1]:2/" but got "http://[:0/"
FAIL <a>: Setting <http://example.net>.host = '[::0:01]:2' IPv6 address syntax is normalized assert_equals: expected "http://[::1]:2/" but got "http://[:0/"
FAIL <area>: Setting <http://example.net>.host = '[::0:01]:2' IPv6 address syntax is normalized assert_equals: expected "http://[::1]:2/" but got "http://[:0/"
PASS URL: Setting <http://example.net>.host = '[::0:01]:2' IPv6 address syntax is normalized
PASS <a>: Setting <http://example.net>.host = '[::0:01]:2' IPv6 address syntax is normalized
PASS <area>: Setting <http://example.net>.host = '[::0:01]:2' IPv6 address syntax is normalized
PASS URL: Setting <http://example.net>.host = '[2001:db8::2]:4002' IPv6 literal address with port, crbug.com/1012416
PASS <a>: Setting <http://example.net>.host = '[2001:db8::2]:4002' IPv6 literal address with port, crbug.com/1012416
PASS <area>: Setting <http://example.net>.host = '[2001:db8::2]:4002' IPv6 literal address with port, crbug.com/1012416
PASS URL: Setting <http://example.net>.host = 'example.com:80' Default port number is removed
PASS <a>: Setting <http://example.net>.host = 'example.com:80' Default port number is removed
PASS <area>: Setting <http://example.net>.host = 'example.com:80' Default port number is removed
......@@ -292,18 +295,18 @@ FAIL <area>: Setting <http://example.net/path>.host = 'example.com:65536' Port n
FAIL URL: Setting <http://example.net/>.host = '[google.com]' Broken IPv6 assert_equals: expected "http://example.net/" but got "http://[google.com]/"
FAIL <a>: Setting <http://example.net/>.host = '[google.com]' Broken IPv6 assert_equals: expected "http://example.net/" but got "http://[google.com]/"
FAIL <area>: Setting <http://example.net/>.host = '[google.com]' Broken IPv6 assert_equals: expected "http://example.net/" but got "http://[google.com]/"
FAIL URL: Setting <http://example.net/>.host = '[::1.2.3.4x]' assert_equals: expected "http://example.net/" but got "http://[:0/"
FAIL <a>: Setting <http://example.net/>.host = '[::1.2.3.4x]' assert_equals: expected "http://example.net/" but got "http://[:0/"
FAIL <area>: Setting <http://example.net/>.host = '[::1.2.3.4x]' assert_equals: expected "http://example.net/" but got "http://[:0/"
FAIL URL: Setting <http://example.net/>.host = '[::1.2.3.]' assert_equals: expected "http://example.net/" but got "http://[:0/"
FAIL <a>: Setting <http://example.net/>.host = '[::1.2.3.]' assert_equals: expected "http://example.net/" but got "http://[:0/"
FAIL <area>: Setting <http://example.net/>.host = '[::1.2.3.]' assert_equals: expected "http://example.net/" but got "http://[:0/"
FAIL URL: Setting <http://example.net/>.host = '[::1.2.]' assert_equals: expected "http://example.net/" but got "http://[:0/"
FAIL <a>: Setting <http://example.net/>.host = '[::1.2.]' assert_equals: expected "http://example.net/" but got "http://[:0/"
FAIL <area>: Setting <http://example.net/>.host = '[::1.2.]' assert_equals: expected "http://example.net/" but got "http://[:0/"
FAIL URL: Setting <http://example.net/>.host = '[::1.]' assert_equals: expected "http://example.net/" but got "http://[:0/"
FAIL <a>: Setting <http://example.net/>.host = '[::1.]' assert_equals: expected "http://example.net/" but got "http://[:0/"
FAIL <area>: Setting <http://example.net/>.host = '[::1.]' assert_equals: expected "http://example.net/" but got "http://[:0/"
FAIL URL: Setting <http://example.net/>.host = '[::1.2.3.4x]' assert_equals: expected "http://example.net/" but got "http://[::1.2.3.4x]/"
FAIL <a>: Setting <http://example.net/>.host = '[::1.2.3.4x]' assert_equals: expected "http://example.net/" but got "http://[::1.2.3.4x]/"
FAIL <area>: Setting <http://example.net/>.host = '[::1.2.3.4x]' assert_equals: expected "http://example.net/" but got "http://[::1.2.3.4x]/"
FAIL URL: Setting <http://example.net/>.host = '[::1.2.3.]' assert_equals: expected "http://example.net/" but got "http://[::102:3]/"
FAIL <a>: Setting <http://example.net/>.host = '[::1.2.3.]' assert_equals: expected "http://example.net/" but got "http://[::102:3]/"
FAIL <area>: Setting <http://example.net/>.host = '[::1.2.3.]' assert_equals: expected "http://example.net/" but got "http://[::102:3]/"
FAIL URL: Setting <http://example.net/>.host = '[::1.2.]' assert_equals: expected "http://example.net/" but got "http://[::100:2]/"
FAIL <a>: Setting <http://example.net/>.host = '[::1.2.]' assert_equals: expected "http://example.net/" but got "http://[::100:2]/"
FAIL <area>: Setting <http://example.net/>.host = '[::1.2.]' assert_equals: expected "http://example.net/" but got "http://[::100:2]/"
FAIL URL: Setting <http://example.net/>.host = '[::1.]' assert_equals: expected "http://example.net/" but got "http://[::1]/"
FAIL <a>: Setting <http://example.net/>.host = '[::1.]' assert_equals: expected "http://example.net/" but got "http://[::1]/"
FAIL <area>: Setting <http://example.net/>.host = '[::1.]' assert_equals: expected "http://example.net/" but got "http://[::1]/"
FAIL URL: Setting <file://y/>.host = 'x:123' assert_equals: expected "file://y/" but got "file://x/"
FAIL <a>: Setting <file://y/>.host = 'x:123' assert_equals: expected "file://y/" but got "file://x/"
FAIL <area>: Setting <file://y/>.host = 'x:123' assert_equals: expected "file://y/" but got "file://x/"
......
This is a testharness.js-based test.
Found 592 tests; 299 PASS, 293 FAIL, 0 TIMEOUT, 0 NOTRUN.
Found 595 tests; 305 PASS, 290 FAIL, 0 TIMEOUT, 0 NOTRUN.
PASS Loading data…
PASS URL: Setting <a://example.net>.protocol = '' The empty string is not a valid scheme. Setter leaves the URL unchanged.
PASS <a>: Setting <a://example.net>.protocol = '' The empty string is not a valid scheme. Setter leaves the URL unchanged.
......@@ -232,9 +232,12 @@ FAIL <area>: Setting <a:/foo>.host = 'example.net' Path-only URLs can gain a hos
PASS URL: Setting <http://example.net>.host = '0x7F000001:8080' IPv4 address syntax is normalized
PASS <a>: Setting <http://example.net>.host = '0x7F000001:8080' IPv4 address syntax is normalized
PASS <area>: Setting <http://example.net>.host = '0x7F000001:8080' IPv4 address syntax is normalized
FAIL URL: Setting <http://example.net>.host = '[::0:01]:2' IPv6 address syntax is normalized assert_equals: expected "http://[::1]:2/" but got "http://[:0/"
FAIL <a>: Setting <http://example.net>.host = '[::0:01]:2' IPv6 address syntax is normalized assert_equals: expected "http://[::1]:2/" but got "http://[:0/"
FAIL <area>: Setting <http://example.net>.host = '[::0:01]:2' IPv6 address syntax is normalized assert_equals: expected "http://[::1]:2/" but got "http://[:0/"
PASS URL: Setting <http://example.net>.host = '[::0:01]:2' IPv6 address syntax is normalized
PASS <a>: Setting <http://example.net>.host = '[::0:01]:2' IPv6 address syntax is normalized
PASS <area>: Setting <http://example.net>.host = '[::0:01]:2' IPv6 address syntax is normalized
PASS URL: Setting <http://example.net>.host = '[2001:db8::2]:4002' IPv6 literal address with port, crbug.com/1012416
PASS <a>: Setting <http://example.net>.host = '[2001:db8::2]:4002' IPv6 literal address with port, crbug.com/1012416
PASS <area>: Setting <http://example.net>.host = '[2001:db8::2]:4002' IPv6 literal address with port, crbug.com/1012416
PASS URL: Setting <http://example.net>.host = 'example.com:80' Default port number is removed
PASS <a>: Setting <http://example.net>.host = 'example.com:80' Default port number is removed
PASS <area>: Setting <http://example.net>.host = 'example.com:80' Default port number is removed
......@@ -292,18 +295,18 @@ FAIL <area>: Setting <http://example.net/path>.host = 'example.com:65536' Port n
FAIL URL: Setting <http://example.net/>.host = '[google.com]' Broken IPv6 assert_equals: expected "http://example.net/" but got "http://[google.com]/"
FAIL <a>: Setting <http://example.net/>.host = '[google.com]' Broken IPv6 assert_equals: expected "http://example.net/" but got "http://[google.com]/"
FAIL <area>: Setting <http://example.net/>.host = '[google.com]' Broken IPv6 assert_equals: expected "http://example.net/" but got "http://[google.com]/"
FAIL URL: Setting <http://example.net/>.host = '[::1.2.3.4x]' assert_equals: expected "http://example.net/" but got "http://[:0/"
FAIL <a>: Setting <http://example.net/>.host = '[::1.2.3.4x]' assert_equals: expected "http://example.net/" but got "http://[:0/"
FAIL <area>: Setting <http://example.net/>.host = '[::1.2.3.4x]' assert_equals: expected "http://example.net/" but got "http://[:0/"
FAIL URL: Setting <http://example.net/>.host = '[::1.2.3.]' assert_equals: expected "http://example.net/" but got "http://[:0/"
FAIL <a>: Setting <http://example.net/>.host = '[::1.2.3.]' assert_equals: expected "http://example.net/" but got "http://[:0/"
FAIL <area>: Setting <http://example.net/>.host = '[::1.2.3.]' assert_equals: expected "http://example.net/" but got "http://[:0/"
FAIL URL: Setting <http://example.net/>.host = '[::1.2.]' assert_equals: expected "http://example.net/" but got "http://[:0/"
FAIL <a>: Setting <http://example.net/>.host = '[::1.2.]' assert_equals: expected "http://example.net/" but got "http://[:0/"
FAIL <area>: Setting <http://example.net/>.host = '[::1.2.]' assert_equals: expected "http://example.net/" but got "http://[:0/"
FAIL URL: Setting <http://example.net/>.host = '[::1.]' assert_equals: expected "http://example.net/" but got "http://[:0/"
FAIL <a>: Setting <http://example.net/>.host = '[::1.]' assert_equals: expected "http://example.net/" but got "http://[:0/"
FAIL <area>: Setting <http://example.net/>.host = '[::1.]' assert_equals: expected "http://example.net/" but got "http://[:0/"
FAIL URL: Setting <http://example.net/>.host = '[::1.2.3.4x]' assert_equals: expected "http://example.net/" but got "http://[::1.2.3.4x]/"
FAIL <a>: Setting <http://example.net/>.host = '[::1.2.3.4x]' assert_equals: expected "http://example.net/" but got "http://[::1.2.3.4x]/"
FAIL <area>: Setting <http://example.net/>.host = '[::1.2.3.4x]' assert_equals: expected "http://example.net/" but got "http://[::1.2.3.4x]/"
FAIL URL: Setting <http://example.net/>.host = '[::1.2.3.]' assert_equals: expected "http://example.net/" but got "http://[::102:3]/"
FAIL <a>: Setting <http://example.net/>.host = '[::1.2.3.]' assert_equals: expected "http://example.net/" but got "http://[::102:3]/"
FAIL <area>: Setting <http://example.net/>.host = '[::1.2.3.]' assert_equals: expected "http://example.net/" but got "http://[::102:3]/"
FAIL URL: Setting <http://example.net/>.host = '[::1.2.]' assert_equals: expected "http://example.net/" but got "http://[::100:2]/"
FAIL <a>: Setting <http://example.net/>.host = '[::1.2.]' assert_equals: expected "http://example.net/" but got "http://[::100:2]/"
FAIL <area>: Setting <http://example.net/>.host = '[::1.2.]' assert_equals: expected "http://example.net/" but got "http://[::100:2]/"
FAIL URL: Setting <http://example.net/>.host = '[::1.]' assert_equals: expected "http://example.net/" but got "http://[::1]/"
FAIL <a>: Setting <http://example.net/>.host = '[::1.]' assert_equals: expected "http://example.net/" but got "http://[::1]/"
FAIL <area>: Setting <http://example.net/>.host = '[::1.]' assert_equals: expected "http://example.net/" but got "http://[::1]/"
FAIL URL: Setting <file://y/>.host = 'x:123' assert_equals: expected "file://y/" but got "file://x/"
FAIL <a>: Setting <file://y/>.host = 'x:123' assert_equals: expected "file://y/" but got "file://x/"
FAIL <area>: Setting <file://y/>.host = 'x:123' assert_equals: expected "file://y/" but got "file://x/"
......
This is a testharness.js-based test.
Found 592 tests; 272 PASS, 320 FAIL, 0 TIMEOUT, 0 NOTRUN.
Found 595 tests; 278 PASS, 317 FAIL, 0 TIMEOUT, 0 NOTRUN.
PASS Loading data…
FAIL URL: Setting <a://example.net>.protocol = '' The empty string is not a valid scheme. Setter leaves the URL unchanged. assert_equals: expected "a://example.net" but got "file:///A://example.net"
FAIL <a>: Setting <a://example.net>.protocol = '' The empty string is not a valid scheme. Setter leaves the URL unchanged. assert_equals: expected "a://example.net" but got "file:///A://example.net"
......@@ -232,9 +232,12 @@ FAIL <area>: Setting <a:/foo>.host = 'example.net' Path-only URLs can gain a hos
PASS URL: Setting <http://example.net>.host = '0x7F000001:8080' IPv4 address syntax is normalized
PASS <a>: Setting <http://example.net>.host = '0x7F000001:8080' IPv4 address syntax is normalized
PASS <area>: Setting <http://example.net>.host = '0x7F000001:8080' IPv4 address syntax is normalized
FAIL URL: Setting <http://example.net>.host = '[::0:01]:2' IPv6 address syntax is normalized assert_equals: expected "http://[::1]:2/" but got "http://[:0/"
FAIL <a>: Setting <http://example.net>.host = '[::0:01]:2' IPv6 address syntax is normalized assert_equals: expected "http://[::1]:2/" but got "http://[:0/"
FAIL <area>: Setting <http://example.net>.host = '[::0:01]:2' IPv6 address syntax is normalized assert_equals: expected "http://[::1]:2/" but got "http://[:0/"
PASS URL: Setting <http://example.net>.host = '[::0:01]:2' IPv6 address syntax is normalized
PASS <a>: Setting <http://example.net>.host = '[::0:01]:2' IPv6 address syntax is normalized
PASS <area>: Setting <http://example.net>.host = '[::0:01]:2' IPv6 address syntax is normalized
PASS URL: Setting <http://example.net>.host = '[2001:db8::2]:4002' IPv6 literal address with port, crbug.com/1012416
PASS <a>: Setting <http://example.net>.host = '[2001:db8::2]:4002' IPv6 literal address with port, crbug.com/1012416
PASS <area>: Setting <http://example.net>.host = '[2001:db8::2]:4002' IPv6 literal address with port, crbug.com/1012416
PASS URL: Setting <http://example.net>.host = 'example.com:80' Default port number is removed
PASS <a>: Setting <http://example.net>.host = 'example.com:80' Default port number is removed
PASS <area>: Setting <http://example.net>.host = 'example.com:80' Default port number is removed
......@@ -292,18 +295,18 @@ FAIL <area>: Setting <http://example.net/path>.host = 'example.com:65536' Port n
FAIL URL: Setting <http://example.net/>.host = '[google.com]' Broken IPv6 assert_equals: expected "http://example.net/" but got "http://[google.com]/"
FAIL <a>: Setting <http://example.net/>.host = '[google.com]' Broken IPv6 assert_equals: expected "http://example.net/" but got "http://[google.com]/"
FAIL <area>: Setting <http://example.net/>.host = '[google.com]' Broken IPv6 assert_equals: expected "http://example.net/" but got "http://[google.com]/"
FAIL URL: Setting <http://example.net/>.host = '[::1.2.3.4x]' assert_equals: expected "http://example.net/" but got "http://[:0/"
FAIL <a>: Setting <http://example.net/>.host = '[::1.2.3.4x]' assert_equals: expected "http://example.net/" but got "http://[:0/"
FAIL <area>: Setting <http://example.net/>.host = '[::1.2.3.4x]' assert_equals: expected "http://example.net/" but got "http://[:0/"
FAIL URL: Setting <http://example.net/>.host = '[::1.2.3.]' assert_equals: expected "http://example.net/" but got "http://[:0/"
FAIL <a>: Setting <http://example.net/>.host = '[::1.2.3.]' assert_equals: expected "http://example.net/" but got "http://[:0/"
FAIL <area>: Setting <http://example.net/>.host = '[::1.2.3.]' assert_equals: expected "http://example.net/" but got "http://[:0/"
FAIL URL: Setting <http://example.net/>.host = '[::1.2.]' assert_equals: expected "http://example.net/" but got "http://[:0/"
FAIL <a>: Setting <http://example.net/>.host = '[::1.2.]' assert_equals: expected "http://example.net/" but got "http://[:0/"
FAIL <area>: Setting <http://example.net/>.host = '[::1.2.]' assert_equals: expected "http://example.net/" but got "http://[:0/"
FAIL URL: Setting <http://example.net/>.host = '[::1.]' assert_equals: expected "http://example.net/" but got "http://[:0/"
FAIL <a>: Setting <http://example.net/>.host = '[::1.]' assert_equals: expected "http://example.net/" but got "http://[:0/"
FAIL <area>: Setting <http://example.net/>.host = '[::1.]' assert_equals: expected "http://example.net/" but got "http://[:0/"
FAIL URL: Setting <http://example.net/>.host = '[::1.2.3.4x]' assert_equals: expected "http://example.net/" but got "http://[::1.2.3.4x]/"
FAIL <a>: Setting <http://example.net/>.host = '[::1.2.3.4x]' assert_equals: expected "http://example.net/" but got "http://[::1.2.3.4x]/"
FAIL <area>: Setting <http://example.net/>.host = '[::1.2.3.4x]' assert_equals: expected "http://example.net/" but got "http://[::1.2.3.4x]/"
FAIL URL: Setting <http://example.net/>.host = '[::1.2.3.]' assert_equals: expected "http://example.net/" but got "http://[::102:3]/"
FAIL <a>: Setting <http://example.net/>.host = '[::1.2.3.]' assert_equals: expected "http://example.net/" but got "http://[::102:3]/"
FAIL <area>: Setting <http://example.net/>.host = '[::1.2.3.]' assert_equals: expected "http://example.net/" but got "http://[::102:3]/"
FAIL URL: Setting <http://example.net/>.host = '[::1.2.]' assert_equals: expected "http://example.net/" but got "http://[::100:2]/"
FAIL <a>: Setting <http://example.net/>.host = '[::1.2.]' assert_equals: expected "http://example.net/" but got "http://[::100:2]/"
FAIL <area>: Setting <http://example.net/>.host = '[::1.2.]' assert_equals: expected "http://example.net/" but got "http://[::100:2]/"
FAIL URL: Setting <http://example.net/>.host = '[::1.]' assert_equals: expected "http://example.net/" but got "http://[::1]/"
FAIL <a>: Setting <http://example.net/>.host = '[::1.]' assert_equals: expected "http://example.net/" but got "http://[::1]/"
FAIL <area>: Setting <http://example.net/>.host = '[::1.]' assert_equals: expected "http://example.net/" but got "http://[::1]/"
FAIL URL: Setting <file://y/>.host = 'x:123' assert_equals: expected "file://y/" but got "file://x/"
FAIL <a>: Setting <file://y/>.host = 'x:123' assert_equals: expected "file://y/" but got "file://x/"
FAIL <area>: Setting <file://y/>.host = 'x:123' assert_equals: expected "file://y/" but got "file://x/"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment