Bug 1324243 - Normalize IPv6 r=manishearth
authorValentin Gosu <valentin.gosu@gmail.com>
Thu, 09 Mar 2017 00:55:05 +0100
changeset 346731 5d7591da1a09e235079f0a677eed2e06009ea755
parent 346730 13c4b94b75e845892d718e3311422fc505161197
child 346732 5bd635e6e535e860dfa2858492e1eb38d407a471
push id38589
push uservalentin.gosu@gmail.com
push dateThu, 09 Mar 2017 11:36:05 +0000
treeherderautoland@5d7591da1a09 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmanishearth
bugs1324243
milestone55.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1324243 - Normalize IPv6 r=manishearth MozReview-Commit-ID: 1UFIdeWrz1E
docshell/test/unit/test_nsDefaultURIFixup_info.js
dom/url/tests/test_url.html
netwerk/base/nsStandardURL.cpp
netwerk/base/rust-url-capi/src/lib.rs
netwerk/base/rust-url-capi/src/rust-url-capi.h
netwerk/test/unit/test_URIs.js
netwerk/test/unit/test_standardurl.js
testing/web-platform/meta/url/a-element-origin-xhtml.xhtml.ini
testing/web-platform/meta/url/a-element-origin.html.ini
testing/web-platform/meta/url/a-element-xhtml.xhtml.ini
testing/web-platform/meta/url/a-element.html.ini
testing/web-platform/meta/url/url-constructor.html.ini
testing/web-platform/meta/url/url-origin.html.ini
testing/web-platform/meta/url/url-setters.html.ini
--- 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