Bug 1324243 - Normalize IPv6 r=mcmanus,manishearth
MozReview-Commit-ID: 1UFIdeWrz1E
--- a/docshell/test/unit/test_nsDefaultURIFixup_info.js
+++ b/docshell/test/unit/test_nsDefaultURIFixup_info.js
@@ -195,21 +195,23 @@ var testcases = [ {
protocolChange: true,
}, {
input: "[fe80:cd00:0:cde:1257:0:211e:729c]",
fixedURI: "http://[fe80:cd00:0:cde:1257:0:211e:729c]/",
alternateURI: "http://[fe80:cd00:0:cde:1257:0:211e:729c]/",
protocolChange: true,
}, {
input: "[64:ff9b::8.8.8.8]",
- fixedURI: "http://[64:ff9b::8.8.8.8]/",
+ fixedURI: "http://[64:ff9b::808:808]/",
+ alternateURI: "http://[64:ff9b::808:808]/",
protocolChange: true
}, {
input: "[64:ff9b::8.8.8.8]/~moz",
- fixedURI: "http://[64:ff9b::8.8.8.8]/~moz",
+ fixedURI: "http://[64:ff9b::808:808]/~moz",
+ alternateURI: "http://[64:ff9b::808:808]/~moz",
protocolChange: true
}, {
input: "[::1][::1]",
keywordLookup: true,
protocolChange: true
}, {
input: "[::1][100",
fixedURI: null,
--- a/dom/url/tests/test_url.html
+++ b/dom/url/tests/test_url.html
@@ -318,18 +318,18 @@
<script>
/** Test for Bug 960014 **/
var url = new URL("http://localhost/");
url.hostname = "[2001::1]";
is(url.hostname, "[2001::1]", "IPv6 hostname");
is(url.href, "http://[2001::1]/");
url.hostname = "[::192.9.5.5]";
- is(url.hostname, "[::192.9.5.5]", "IPv6 hostname");
- is(url.href, "http://[::192.9.5.5]/");
+ is(url.hostname, "[::c009:505]", "IPv6 hostname");
+ is(url.href, "http://[::c009:505]/");
url = new URL("http://localhost/");
url.hostname = "[::]";
is(url.hostname, "[::]", "IPv6 hostname");
url = new URL("http://localhost/");
url.host = "[2001::1]:30";
is(url.hostname, "[2001::1]", "IPv6 hostname");
--- a/netwerk/base/nsStandardURL.cpp
+++ b/netwerk/base/nsStandardURL.cpp
@@ -768,17 +768,25 @@ nsStandardURL::BuildNormalizedSpec(const
return NS_ERROR_MALFORMED_URI; // don't allow spaces in the hostname
nsresult rv = NormalizeIDN(tempHost, encHost);
if (NS_FAILED(rv)) {
return rv;
}
if (!SegmentIs(spec, mScheme, "resource") &&
!SegmentIs(spec, mScheme, "chrome")) {
nsAutoCString ipString;
- if (NS_SUCCEEDED(NormalizeIPv4(encHost, ipString))) {
+ if (encHost.Length() > 0 &&
+ encHost.First() == '[' && encHost.Last() == ']' &&
+ ValidIPv6orHostname(encHost.get(), encHost.Length())) {
+ rv = (nsresult) rusturl_parse_ipv6addr(&encHost, &ipString);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ encHost = ipString;
+ } else if (NS_SUCCEEDED(NormalizeIPv4(encHost, ipString))) {
encHost = ipString;
}
}
// NormalizeIDN always copies, if the call was successful.
useEncHost = true;
approxLen += encHost.Length();
@@ -2009,17 +2017,25 @@ nsStandardURL::SetHost(const nsACString
nsAutoCString hostBuf;
nsresult rv = NormalizeIDN(flat, hostBuf);
if (NS_FAILED(rv)) {
return rv;
}
if (!SegmentIs(mScheme, "resource") && !SegmentIs(mScheme, "chrome")) {
nsAutoCString ipString;
- if (NS_SUCCEEDED(NormalizeIPv4(hostBuf, ipString))) {
+ if (hostBuf.Length() > 0 &&
+ hostBuf.First() == '[' && hostBuf.Last() == ']' &&
+ ValidIPv6orHostname(hostBuf.get(), hostBuf.Length())) {
+ rv = (nsresult) rusturl_parse_ipv6addr(&hostBuf, &ipString);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ hostBuf = ipString;
+ } else if (NS_SUCCEEDED(NormalizeIPv4(hostBuf, ipString))) {
hostBuf = ipString;
}
}
// NormalizeIDN always copies if the call was successful
host = hostBuf.get();
len = hostBuf.Length();
--- a/netwerk/base/rust-url-capi/src/lib.rs
+++ b/netwerk/base/rust-url-capi/src/lib.rs
@@ -520,8 +520,24 @@ pub extern "C" fn rusturl_relative_spec(
cont.assign(&buffer);
NSError::OK.error_code()
}
#[no_mangle]
pub extern "C" fn sizeof_rusturl() -> size_t {
mem::size_of::<Url>()
}
+
+#[no_mangle]
+pub extern "C" fn rusturl_parse_ipv6addr(input: &nsACString, cont: &mut nsACString) -> i32 {
+ let ip6 = match str::from_utf8(input) {
+ Ok(content) => content,
+ Err(_) => return ParseError::InvalidDomainCharacter.error_code()
+ };
+
+ let h = match url::Host::parse(ip6) {
+ Ok(host) => host,
+ Err(e) => return e.error_code()
+ };
+
+ cont.assign(&h.to_string());
+ NSError::OK.error_code()
+}
--- a/netwerk/base/rust-url-capi/src/rust-url-capi.h
+++ b/netwerk/base/rust-url-capi/src/rust-url-capi.h
@@ -42,13 +42,15 @@ int32_t rusturl_set_port_no(rusturl* url
int32_t rusturl_set_path(rusturl* url, const nsACString* path);
int32_t rusturl_set_query(rusturl* url, const nsACString* query);
int32_t rusturl_set_fragment(rusturl* url, const nsACString* fragment);
int32_t rusturl_resolve(const rusturl* url, const nsACString* relative, nsACString* cont);
int32_t rusturl_common_base_spec(const rusturl* url1, const rusturl* url2, nsACString* cont);
int32_t rusturl_relative_spec(const rusturl* url1, const rusturl* url2, nsACString* cont);
+int32_t rusturl_parse_ipv6addr(const nsACString* input, nsACString* cont);
+
size_t sizeof_rusturl();
}
#endif // __RUST_URL_CAPI
--- a/netwerk/test/unit/test_URIs.js
+++ b/netwerk/test/unit/test_URIs.js
@@ -145,18 +145,18 @@ var gTests = [
scheme: "http",
prePath: "http://10.32.4.239",
host: "10.32.4.239",
path: "/",
ref: "",
nsIURL: true, nsINestedURI: false },
{ spec: "http://[::192.9.5.5]/ipng",
scheme: "http",
- prePath: "http://[::192.9.5.5]",
- host: "::192.9.5.5",
+ prePath: "http://[::c009:505]",
+ host: "::c009:505",
path: "/ipng",
ref: "",
nsIURL: true, nsINestedURI: false },
{ spec: "http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:8888/index.html",
scheme: "http",
prePath: "http://[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:8888",
host: "fedc:ba98:7654:3210:fedc:ba98:7654:3210",
port: 8888,
--- a/netwerk/test/unit/test_standardurl.js
+++ b/netwerk/test/unit/test_standardurl.js
@@ -456,8 +456,16 @@ add_test(function test_invalidHostChars(
for (let c of "@[]*<>|:\"") {
Assert.throws(() => { url.host = "a" + c; }, "Trying to set hostname containing char: " + c);
}
// It also can't contain /, \, #, ?, but we treat these characters as
// hostname separators, so there is no way to set them and fail.
run_next_test();
});
+
+add_test(function test_normalize_ipv6() {
+ var url = stringToURL("http://example.com");
+ url.host = "[::192.9.5.5]";
+ do_check_eq(url.spec, "http://[::c009:505]/");
+
+ run_next_test();
+});
--- a/testing/web-platform/meta/url/a-element-origin-xhtml.xhtml.ini
+++ b/testing/web-platform/meta/url/a-element-origin-xhtml.xhtml.ini
@@ -1,22 +1,16 @@
[a-element-origin-xhtml.xhtml]
type: testharness
[Parsing origin: <https://:@test> against <about:blank>]
expected: FAIL
[Parsing origin: <http://::@c@d:2> against <http://example.org/foo/bar>]
expected: FAIL
- [Parsing origin: <http://[::127.0.0.1\]> against <http://example.org/foo/bar>]
- expected: FAIL
-
- [Parsing origin: <http://[0:0:0:0:0:0:13.1.68.3\]> against <http://example.org/foo/bar>]
- expected: FAIL
-
[Parsing origin: <gopher:/example.com/> against <http://example.org/foo/bar>]
expected: FAIL
[Parsing origin: <data:/example.com/> against <http://example.org/foo/bar>]
expected: FAIL
[Parsing origin: <gopher:example.com/> against <http://example.org/foo/bar>]
expected: FAIL
@@ -100,14 +94,11 @@
expected: FAIL
[Parsing origin: <ftp://%e2%98%83> against <about:blank>]
expected: FAIL
[Parsing origin: <https://%e2%98%83> against <about:blank>]
expected: FAIL
- [Parsing origin: <http://[1:0::\]> against <http://example.net/>]
- expected: FAIL
-
[Parsing origin: <?x> against <sc://ñ>]
expected: FAIL
--- a/testing/web-platform/meta/url/a-element-origin.html.ini
+++ b/testing/web-platform/meta/url/a-element-origin.html.ini
@@ -1,22 +1,16 @@
[a-element-origin.html]
type: testharness
[Parsing origin: <https://:@test> against <about:blank>]
expected: FAIL
[Parsing origin: <http://::@c@d:2> against <http://example.org/foo/bar>]
expected: FAIL
- [Parsing origin: <http://[::127.0.0.1\]> against <http://example.org/foo/bar>]
- expected: FAIL
-
- [Parsing origin: <http://[0:0:0:0:0:0:13.1.68.3\]> against <http://example.org/foo/bar>]
- expected: FAIL
-
[Parsing origin: <gopher:/example.com/> against <http://example.org/foo/bar>]
expected: FAIL
[Parsing origin: <data:/example.com/> against <http://example.org/foo/bar>]
expected: FAIL
[Parsing origin: <gopher:example.com/> against <http://example.org/foo/bar>]
expected: FAIL
@@ -100,14 +94,11 @@
expected: FAIL
[Parsing origin: <ftp://%e2%98%83> against <about:blank>]
expected: FAIL
[Parsing origin: <https://%e2%98%83> against <about:blank>]
expected: FAIL
- [Parsing origin: <http://[1:0::\]> against <http://example.net/>]
- expected: FAIL
-
[Parsing origin: <?x> against <sc://ñ>]
expected: FAIL
--- a/testing/web-platform/meta/url/a-element-xhtml.xhtml.ini
+++ b/testing/web-platform/meta/url/a-element-xhtml.xhtml.ini
@@ -409,22 +409,16 @@
expected: FAIL
[Parsing: <http:> against <https://example.org/foo/bar>]
expected: FAIL
[Parsing: <tel:1234567890> against <http://example.org/foo/bar>]
expected: FAIL
- [Parsing: <http://[::127.0.0.1\]> against <http://example.org/foo/bar>]
- expected: FAIL
-
- [Parsing: <http://[0:0:0:0:0:0:13.1.68.3\]> against <http://example.org/foo/bar>]
- expected: FAIL
-
[Parsing: <https://test:@test> against <about:blank>]
expected: FAIL
[Parsing: <https://:@test> against <about:blank>]
expected: FAIL
[Parsing: <non-special://test:@test/x> against <about:blank>]
expected: FAIL
@@ -546,19 +540,16 @@
if debug and not e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
if not debug and not e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
if debug and e10s and (os == "win") and (version == "6.2.9200") and (processor == "x86_64") and (bits == 64): FAIL
if not debug and e10s and (os == "win") and (version == "6.2.9200") and (processor == "x86_64") and (bits == 64): FAIL
if not debug and not e10s and (os == "win") and (version == "6.2.9200") and (processor == "x86_64") and (bits == 64): FAIL
if debug and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
if debug and not e10s and (os == "win") and (version == "6.2.9200") and (processor == "x86_64") and (bits == 64): FAIL
- [Parsing: <http://[1:0::\]> against <http://example.net/>]
- expected: FAIL
-
[Parsing: <http://?> against <about:blank>]
expected: FAIL
[Parsing: <http://#> against <about:blank>]
expected: FAIL
[Parsing: <sc://ñ> against <about:blank>]
expected: FAIL
--- a/testing/web-platform/meta/url/a-element.html.ini
+++ b/testing/web-platform/meta/url/a-element.html.ini
@@ -418,22 +418,16 @@
expected: FAIL
[Parsing: <http:> against <https://example.org/foo/bar>]
expected: FAIL
[Parsing: <tel:1234567890> against <http://example.org/foo/bar>]
expected: FAIL
- [Parsing: <http://[::127.0.0.1\]> against <http://example.org/foo/bar>]
- expected: FAIL
-
- [Parsing: <http://[0:0:0:0:0:0:13.1.68.3\]> against <http://example.org/foo/bar>]
- expected: FAIL
-
[Parsing: <https://test:@test> against <about:blank>]
expected: FAIL
[Parsing: <https://:@test> against <about:blank>]
expected: FAIL
[Parsing: <non-special://test:@test/x> against <about:blank>]
expected: FAIL
@@ -555,19 +549,16 @@
if debug and not e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
if not debug and not e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
if debug and e10s and (os == "win") and (version == "6.2.9200") and (processor == "x86_64") and (bits == 64): FAIL
if not debug and e10s and (os == "win") and (version == "6.2.9200") and (processor == "x86_64") and (bits == 64): FAIL
if not debug and not e10s and (os == "win") and (version == "6.2.9200") and (processor == "x86_64") and (bits == 64): FAIL
if debug and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
if debug and not e10s and (os == "win") and (version == "6.2.9200") and (processor == "x86_64") and (bits == 64): FAIL
- [Parsing: <http://[1:0::\]> against <http://example.net/>]
- expected: FAIL
-
[Parsing: <http://?> against <about:blank>]
expected: FAIL
[Parsing: <http://#> against <about:blank>]
expected: FAIL
[Parsing: <sc://ñ> against <about:blank>]
expected: FAIL
--- a/testing/web-platform/meta/url/url-constructor.html.ini
+++ b/testing/web-platform/meta/url/url-constructor.html.ini
@@ -196,22 +196,16 @@
expected: FAIL
[Parsing: <sc://ñ.test/> against <about:blank>]
expected: FAIL
[Parsing: <file:..> against <http://www.example.com/test>]
expected: FAIL
- [Parsing: <http://[::127.0.0.1\]> against <http://example.org/foo/bar>]
- expected: FAIL
-
- [Parsing: <http://[0:0:0:0:0:0:13.1.68.3\]> against <http://example.org/foo/bar>]
- expected: FAIL
-
[Parsing: <https://test:@test> against <about:blank>]
expected: FAIL
[Parsing: <https://:@test> against <about:blank>]
expected: FAIL
[Parsing: <non-special://test:@test/x> against <about:blank>]
expected: FAIL
@@ -309,19 +303,16 @@
if debug and not e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
if not debug and not e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
if debug and e10s and (os == "win") and (version == "6.2.9200") and (processor == "x86_64") and (bits == 64): FAIL
if not debug and e10s and (os == "win") and (version == "6.2.9200") and (processor == "x86_64") and (bits == 64): FAIL
if not debug and not e10s and (os == "win") and (version == "6.2.9200") and (processor == "x86_64") and (bits == 64): FAIL
if debug and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
if debug and not e10s and (os == "win") and (version == "6.2.9200") and (processor == "x86_64") and (bits == 64): FAIL
- [Parsing: <http://[1:0::\]> against <http://example.net/>]
- expected: FAIL
-
[Parsing: <sc://ñ> against <about:blank>]
expected: FAIL
[Parsing: <sc://ñ?x> against <about:blank>]
expected: FAIL
[Parsing: <sc://ñ#x> against <about:blank>]
expected: FAIL
--- a/testing/web-platform/meta/url/url-origin.html.ini
+++ b/testing/web-platform/meta/url/url-origin.html.ini
@@ -1,22 +1,16 @@
[url-origin.html]
type: testharness
[Origin parsing: <https://:@test> against <about:blank>]
expected: FAIL
[Origin parsing: <http://::@c@d:2> against <http://example.org/foo/bar>]
expected: FAIL
- [Origin parsing: <http://[::127.0.0.1\]> against <http://example.org/foo/bar>]
- expected: FAIL
-
- [Origin parsing: <http://[0:0:0:0:0:0:13.1.68.3\]> against <http://example.org/foo/bar>]
- expected: FAIL
-
[Origin parsing: <gopher:/example.com/> against <http://example.org/foo/bar>]
expected: FAIL
[Origin parsing: <data:/example.com/> against <http://example.org/foo/bar>]
expected: FAIL
[Origin parsing: <gopher:example.com/> against <http://example.org/foo/bar>]
expected: FAIL
@@ -100,14 +94,11 @@
expected: FAIL
[Origin parsing: <ftp://%e2%98%83> against <about:blank>]
expected: FAIL
[Origin parsing: <https://%e2%98%83> against <about:blank>]
expected: FAIL
- [Origin parsing: <http://[1:0::\]> against <http://example.net/>]
- expected: FAIL
-
[Origin parsing: <?x> against <sc://ñ>]
expected: FAIL
--- a/testing/web-platform/meta/url/url-setters.html.ini
+++ b/testing/web-platform/meta/url/url-setters.html.ini
@@ -223,25 +223,16 @@
expected: FAIL
[<a>: Setting <a:/foo>.host = 'example.net' Path-only URLs can gain a host]
expected: FAIL
[<area>: Setting <a:/foo>.host = 'example.net' Path-only URLs can gain a host]
expected: FAIL
- [URL: Setting <http://example.net>.host = '[::0:01\]:2' IPv6 address syntax is normalized]
- expected: FAIL
-
- [<a>: Setting <http://example.net>.host = '[::0:01\]:2' IPv6 address syntax is normalized]
- expected: FAIL
-
- [<area>: Setting <http://example.net>.host = '[::0:01\]:2' IPv6 address syntax is normalized]
- expected: FAIL
-
[URL: Setting <view-source+http://example.net/path>.host = 'example.com\\stuff' \\ is not a delimiter for non-special schemes, and it’s invalid in a domain]
expected: FAIL
[<a>: Setting <view-source+http://example.net/path>.host = 'example.com\\stuff' \\ is not a delimiter for non-special schemes, and it’s invalid in a domain]
expected: FAIL
[<area>: Setting <view-source+http://example.net/path>.host = 'example.com\\stuff' \\ is not a delimiter for non-special schemes, and it’s invalid in a domain]
expected: FAIL
@@ -268,25 +259,16 @@
expected: FAIL
[<a>: Setting <a:/foo>.hostname = 'example.net' Path-only URLs can gain a host]
expected: FAIL
[<area>: Setting <a:/foo>.hostname = 'example.net' Path-only URLs can gain a host]
expected: FAIL
- [URL: Setting <http://example.net>.hostname = '[::0:01\]' IPv6 address syntax is normalized]
- expected: FAIL
-
- [<a>: Setting <http://example.net>.hostname = '[::0:01\]' IPv6 address syntax is normalized]
- expected: FAIL
-
- [<area>: Setting <http://example.net>.hostname = '[::0:01\]' IPv6 address syntax is normalized]
- expected: FAIL
-
[URL: Setting <http://example.net/path>.hostname = 'example.com:8080' Stuff after a : delimiter is ignored]
expected: FAIL
[<a>: Setting <http://example.net/path>.hostname = 'example.com:8080' Stuff after a : delimiter is ignored]
expected: FAIL
[<area>: Setting <http://example.net/path>.hostname = 'example.com:8080' Stuff after a : delimiter is ignored]
expected: FAIL