Skip to content

Commit 71ecb2c

Browse files
committed
Fix roundtripping issue
1 parent 22b925f commit 71ecb2c

File tree

2 files changed

+29
-9
lines changed

2 files changed

+29
-9
lines changed

url/src/host.rs

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -151,16 +151,27 @@ impl<'a> Host<Cow<'a, str>> {
151151
};
152152

153153
if input.find(is_invalid_host_char).is_some() {
154-
Err(ParseError::InvalidDomainCharacter)
155-
} else {
156-
Ok(Host::Domain(
157-
match utf8_percent_encode(&input, CONTROLS).into() {
158-
Cow::Owned(v) => Cow::Owned(v),
159-
// if we're borrowing, then we can return the original Cow
160-
Cow::Borrowed(_) => input,
161-
},
162-
))
154+
return Err(ParseError::InvalidDomainCharacter);
163155
}
156+
157+
// Call utf8_percent_encode and use the result.
158+
// Note: This returns Cow::Borrowed for single-item results (either from input
159+
// or from the static encoding table), and Cow::Owned for multi-item results.
160+
// We cannot distinguish between "borrowed from input" vs "borrowed from static table"
161+
// based on the Cow variant alone.
162+
Ok(Host::Domain(
163+
match utf8_percent_encode(&input, CONTROLS).into() {
164+
Cow::Owned(v) => Cow::Owned(v),
165+
// If we're borrowing, we need to check if it's the same as the input
166+
Cow::Borrowed(v) => {
167+
if v == &*input {
168+
input // No encoding happened, reuse original
169+
} else {
170+
Cow::Owned(v.to_owned()) // Borrowed from static table, need to own it
171+
}
172+
}
173+
}
174+
))
164175
}
165176

166177
pub(crate) fn into_owned(self) -> Host<String> {

url/tests/unit.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1383,3 +1383,12 @@ fn serde_error_message() {
13831383
r#"relative URL without a base: "§invalid#+#*Ä" at line 1 column 25"#
13841384
);
13851385
}
1386+
1387+
#[test]
1388+
fn test_parse_url_with_single_byte_control_host() {
1389+
let input = "l://\x01:";
1390+
1391+
let url1 = Url::parse(input).unwrap();
1392+
let url2 = Url::parse(url1.as_str()).unwrap();
1393+
assert_eq!(url2, url1);
1394+
}

0 commit comments

Comments
 (0)