Pārlūkot izejas kodu

Properly handle empty username and/or password

Valentin Gosu 9 gadi atpakaļ
vecāks
revīzija
2f479abc27
3 mainītis faili ar 108 papildinājumiem un 7 dzēšanām
  1. 13 2
      src/parser.rs
  2. 1 1
      tests/unit.rs
  3. 94 4
      tests/urltestdata.json

+ 13 - 2
src/parser.rs

@@ -701,14 +701,23 @@ impl<'a> Parser<'a> {
         };
 
         let mut username_end = None;
+        let mut has_password = false;
+        let mut has_username = false;
         while userinfo_char_count > 0 {
             let (c, utf8_c) = input.next_utf8().unwrap();
             userinfo_char_count -= 1;
             if c == ':' && username_end.is_none() {
                 // Start parsing password
                 username_end = Some(to_u32(self.serialization.len())?);
-                self.serialization.push(':');
+                // We don't add a colon if the password is empty
+                if userinfo_char_count > 0 {
+                    self.serialization.push(':');
+                    has_password = true;
+                }
             } else {
+                if !has_password {
+                    has_username = true;
+                }
                 self.check_url_code_point(c, &input);
                 self.serialization.extend(utf8_percent_encode(utf8_c, USERINFO_ENCODE_SET));
             }
@@ -717,7 +726,9 @@ impl<'a> Parser<'a> {
             Some(i) => i,
             None => to_u32(self.serialization.len())?,
         };
-        self.serialization.push('@');
+        if has_username || has_password {
+            self.serialization.push('@');
+        }
         Ok((username_end, remaining))
     }
 

+ 1 - 1
tests/unit.rs

@@ -221,7 +221,7 @@ fn test_serialization() {
         ("http://example.com/", "http://example.com/"),
         ("http://addslash.com", "http://addslash.com/"),
         ("http://@emptyuser.com/", "http://emptyuser.com/"),
-        ("http://:@emptypass.com/", "http://:@emptypass.com/"),
+        ("http://:@emptypass.com/", "http://emptypass.com/"),
         ("http://user@user.com/", "http://user@user.com/"),
         ("http://user:pass@userpass.com/", "http://user:pass@userpass.com/"),
         ("http://slashquery.com/path/?q=something", "http://slashquery.com/path/?q=something"),

+ 94 - 4
tests/urltestdata.json

@@ -30,6 +30,36 @@
     "search": "?b",
     "hash": "#c"
   },
+  {
+    "input": "https://test:@test",
+    "base": "about:blank",
+    "href": "https://test@test/",
+    "origin": "https://test",
+    "protocol": "https:",
+    "username": "test",
+    "password": "",
+    "host": "test",
+    "hostname": "test",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "https://:@test",
+    "base": "about:blank",
+    "href": "https://test/",
+    "origin": "https://test",
+    "protocol": "https:",
+    "username": "",
+    "password": "",
+    "host": "test",
+    "hostname": "test",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
   {
     "input": "http:foo.com",
     "base": "http://example.org/foo/bar",
@@ -3096,7 +3126,7 @@
   {
     "input": "http:a:@www.example.com",
     "base": "about:blank",
-    "href": "http://a:@www.example.com/",
+    "href": "http://a@www.example.com/",
     "origin": "http://www.example.com",
     "protocol": "http:",
     "username": "a",
@@ -3111,7 +3141,7 @@
   {
     "input": "http:/a:@www.example.com",
     "base": "about:blank",
-    "href": "http://a:@www.example.com/",
+    "href": "http://a@www.example.com/",
     "origin": "http://www.example.com",
     "protocol": "http:",
     "username": "a",
@@ -3126,7 +3156,7 @@
   {
     "input": "http://a:@www.example.com",
     "base": "about:blank",
-    "href": "http://a:@www.example.com/",
+    "href": "http://a@www.example.com/",
     "origin": "http://www.example.com",
     "protocol": "http:",
     "username": "a",
@@ -3171,7 +3201,67 @@
   {
     "input": "http://:@www.example.com",
     "base": "about:blank",
-    "href": "http://:@www.example.com/",
+    "href": "http://www.example.com/",
+    "origin": "http://www.example.com",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "www.example.com",
+    "hostname": "www.example.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http:a:@www.example.com",
+    "base": "about:blank",
+    "href": "http://a@www.example.com/",
+    "origin": "http://www.example.com",
+    "protocol": "http:",
+    "username": "a",
+    "password": "",
+    "host": "www.example.com",
+    "hostname": "www.example.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http:/a:@www.example.com",
+    "base": "about:blank",
+    "href": "http://a@www.example.com/",
+    "origin": "http://www.example.com",
+    "protocol": "http:",
+    "username": "a",
+    "password": "",
+    "host": "www.example.com",
+    "hostname": "www.example.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://a:@www.example.com",
+    "base": "about:blank",
+    "href": "http://a@www.example.com/",
+    "origin": "http://www.example.com",
+    "protocol": "http:",
+    "username": "a",
+    "password": "",
+    "host": "www.example.com",
+    "hostname": "www.example.com",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://:@www.example.com",
+    "base": "about:blank",
+    "href": "http://www.example.com/",
     "origin": "http://www.example.com",
     "protocol": "http:",
     "username": "",