瀏覽代碼

Fix roundtripping issue (#1079)

* Fix roundtripping issue

* Skip running doctests with sanitizer due to mixing  will cause an ABI mismatch in crate
Valentin Gosu 11 月之前
父節點
當前提交
9771ab51f0
共有 3 個文件被更改,包括 30 次插入10 次删除
  1. 1 1
      .github/workflows/main.yml
  2. 20 9
      url/src/host.rs
  3. 9 0
      url/tests/unit.rs

+ 1 - 1
.github/workflows/main.yml

@@ -100,7 +100,7 @@ jobs:
             echo "Running tests with $sanitizer sanitizer..."
             export RUSTFLAGS="-Z sanitizer=$sanitizer"
             export RUSTDOCFLAGS="$RUSTFLAGS"
-            cargo +nightly test -Z build-std --target "$TARGET"
+            cargo +nightly test -Z build-std --target "$TARGET" --lib --tests
           done
 
   WASM:

+ 20 - 9
url/src/host.rs

@@ -151,16 +151,27 @@ impl<'a> Host<Cow<'a, str>> {
         };
 
         if input.find(is_invalid_host_char).is_some() {
-            Err(ParseError::InvalidDomainCharacter)
-        } else {
-            Ok(Host::Domain(
-                match utf8_percent_encode(&input, CONTROLS).into() {
-                    Cow::Owned(v) => Cow::Owned(v),
-                    // if we're borrowing, then we can return the original Cow
-                    Cow::Borrowed(_) => input,
-                },
-            ))
+            return Err(ParseError::InvalidDomainCharacter);
         }
+
+        // Call utf8_percent_encode and use the result.
+        // Note: This returns Cow::Borrowed for single-item results (either from input
+        // or from the static encoding table), and Cow::Owned for multi-item results.
+        // We cannot distinguish between "borrowed from input" vs "borrowed from static table"
+        // based on the Cow variant alone.
+        Ok(Host::Domain(
+            match utf8_percent_encode(&input, CONTROLS).into() {
+                Cow::Owned(v) => Cow::Owned(v),
+                // If we're borrowing, we need to check if it's the same as the input
+                Cow::Borrowed(v) => {
+                    if v == &*input {
+                        input // No encoding happened, reuse original
+                    } else {
+                        Cow::Owned(v.to_owned()) // Borrowed from static table, need to own it
+                    }
+                }
+            },
+        ))
     }
 
     pub(crate) fn into_owned(self) -> Host<String> {

+ 9 - 0
url/tests/unit.rs

@@ -1383,3 +1383,12 @@ fn serde_error_message() {
         r#"relative URL without a base: "§invalid#+#*Ä" at line 1 column 25"#
     );
 }
+
+#[test]
+fn test_parse_url_with_single_byte_control_host() {
+    let input = "l://\x01:";
+
+    let url1 = Url::parse(input).unwrap();
+    let url2 = Url::parse(url1.as_str()).unwrap();
+    assert_eq!(url2, url1);
+}