Просмотр исходного кода

Fix support for for IPv4-in-IPv6 syntax.

Simon Sapin 10 лет назад
Родитель
Сommit
8be40ffd06
4 измененных файлов с 52 добавлено и 9 удалено
  1. 1 1
      Cargo.toml
  2. 17 7
      src/host.rs
  3. 4 1
      src/lib.rs
  4. 30 0
      tests/urltestdata.json

+ 1 - 1
Cargo.toml

@@ -1,7 +1,7 @@
 [package]
 [package]
 
 
 name = "url"
 name = "url"
-version = "1.2.2"
+version = "1.2.3"
 authors = ["The rust-url developers"]
 authors = ["The rust-url developers"]
 
 
 description = "URL library for Rust, based on the WHATWG URL Standard"
 description = "URL library for Rust, based on the WHATWG URL Standard"

+ 17 - 7
src/host.rs

@@ -371,23 +371,33 @@ fn parse_ipv6addr(input: &str) -> ParseResult<Ipv6Addr> {
         }
         }
         let mut dots_seen = 0;
         let mut dots_seen = 0;
         while i < len {
         while i < len {
-            // FIXME: https://github.com/whatwg/url/commit/1c22aa119c354e0020117e02571cec53f7c01064
-            let mut value = 0u16;
+            let mut value = None;
             while i < len {
             while i < len {
                 let digit = match input[i] {
                 let digit = match input[i] {
                     c @ b'0' ... b'9' => c - b'0',
                     c @ b'0' ... b'9' => c - b'0',
                     _ => break
                     _ => break
                 };
                 };
-                value = value * 10 + digit as u16;
-                if value == 0 || value > 255 {
-                    return Err(ParseError::InvalidIpv6Address)
+                match value {
+                    None => value = Some(digit as u16),
+                    Some(0) => return Err(ParseError::InvalidIpv6Address),  // No leading zero
+                    Some(ref mut v) => {
+                        *v = *v * 10 + digit as u16;
+                        if *v > 255 {
+                            return Err(ParseError::InvalidIpv6Address)
+                        }
+                    }
                 }
                 }
+                i += 1;
             }
             }
             if dots_seen < 3 && !(i < len && input[i] == b'.') {
             if dots_seen < 3 && !(i < len && input[i] == b'.') {
                 return Err(ParseError::InvalidIpv6Address)
                 return Err(ParseError::InvalidIpv6Address)
             }
             }
-            pieces[piece_pointer] = pieces[piece_pointer] * 0x100 + value;
-            if dots_seen == 0 || dots_seen == 2 {
+            pieces[piece_pointer] = if let Some(v) = value {
+                pieces[piece_pointer] * 0x100 + v
+            } else {
+                return Err(ParseError::InvalidIpv6Address)
+            };
+            if dots_seen == 1 || dots_seen == 3 {
                 piece_pointer += 1;
                 piece_pointer += 1;
             }
             }
             i += 1;
             i += 1;

+ 4 - 1
src/lib.rs

@@ -314,7 +314,10 @@ impl Url {
             match self.host {
             match self.host {
                 HostInternal::None => assert_eq!(host_str, ""),
                 HostInternal::None => assert_eq!(host_str, ""),
                 HostInternal::Ipv4(address) => assert_eq!(host_str, address.to_string()),
                 HostInternal::Ipv4(address) => assert_eq!(host_str, address.to_string()),
-                HostInternal::Ipv6(address) => assert_eq!(host_str, format!("[{}]", address)),
+                HostInternal::Ipv6(address) => {
+                    let h: Host<String> = Host::Ipv6(address);
+                    assert_eq!(host_str, h.to_string())
+                }
                 HostInternal::Domain => {
                 HostInternal::Domain => {
                     if SchemeType::from(self.scheme()).is_special() {
                     if SchemeType::from(self.scheme()).is_special() {
                         assert!(!host_str.is_empty())
                         assert!(!host_str.is_empty())

+ 30 - 0
tests/urltestdata.json

@@ -840,6 +840,36 @@
     "search": "",
     "search": "",
     "hash": ""
     "hash": ""
   },
   },
+  {
+    "input": "http://[::127.0.0.1]",
+    "base": "http://example.org/foo/bar",
+    "href": "http://[::7f00:1]/",
+    "origin": "http://[::7f00:1]",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "[::7f00:1]",
+    "hostname": "[::7f00:1]",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://[0:0:0:0:0:0:13.1.68.3]",
+    "base": "http://example.org/foo/bar",
+    "href": "http://[::d01:4403]/",
+    "origin": "http://[::d01:4403]",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "[::d01:4403]",
+    "hostname": "[::d01:4403]",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
   {
   {
     "input": "http://[2001::1]:80",
     "input": "http://[2001::1]:80",
     "base": "http://example.org/foo/bar",
     "base": "http://example.org/foo/bar",