Skip to content

Commit 2803c0d

Browse files
committed
Somehow cannot be a base did not do what its documentation suggested.
1 parent f167497 commit 2803c0d

File tree

3 files changed

+37
-15
lines changed

3 files changed

+37
-15
lines changed

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -687,7 +687,7 @@ impl Url {
687687
/// ```
688688
#[inline]
689689
pub fn cannot_be_a_base(&self) -> bool {
690-
!self.slice(self.path_start..).starts_with('/')
690+
!self.slice(self.scheme_end + 1..).starts_with('/')
691691
}
692692

693693
/// Return the username for this URL (typically the empty string)

src/parser.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -912,6 +912,14 @@ impl<'a> Parser<'a> {
912912
let (host, remaining) = Parser::parse_host(input, scheme_type)?;
913913
write!(&mut self.serialization, "{}", host).unwrap();
914914
let host_end = to_u32(self.serialization.len())?;
915+
if remaining.starts_with(":") {
916+
// Port with an empty host
917+
if let Host::Domain(h) = &host {
918+
if h.is_empty() {
919+
return Err(ParseError::EmptyHost);
920+
}
921+
}
922+
}
915923
let (port, remaining) = if let Some(remaining) = remaining.split_prefix(':') {
916924
let scheme = || default_port(&self.serialization[..scheme_end as usize]);
917925
Parser::parse_port(remaining, scheme, self.context)?

src/quirks.rs

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -99,14 +99,13 @@ pub fn host(url: &Url) -> &str {
9999

100100
/// Setter for https://url.spec.whatwg.org/#dom-url-host
101101
pub fn set_host(url: &mut Url, new_host: &str) -> Result<(), ()> {
102+
// If context object’s url’s cannot-be-a-base-URL flag is set, then return.
103+
if url.cannot_be_a_base() {
104+
return Err(());
105+
}
102106
let host;
103107
let opt_port;
104108
{
105-
// If context object’s url’s cannot-be-a-base-URL flag is set, then return.
106-
if url.cannot_be_a_base() {
107-
return Err(());
108-
}
109-
110109
let scheme = url.scheme();
111110
let result = Parser::parse_host(Input::new(new_host), SchemeType::from(scheme));
112111
match result {
@@ -158,6 +157,20 @@ pub fn set_hostname(url: &mut Url, new_hostname: &str) -> Result<(), ()> {
158157
}
159158
let result = Parser::parse_host(Input::new(new_hostname), SchemeType::from(url.scheme()));
160159
if let Ok((host, _remaining)) = result {
160+
if let Host::Domain(h) = &host {
161+
if h.is_empty() {
162+
// Empty host on special url
163+
if SchemeType::from(url.scheme()).is_special()
164+
// Port with an empty host
165+
||!port(&url).is_empty()
166+
// Empty host with includes credentials
167+
|| !url.username().is_empty()
168+
|| !url.password().unwrap_or(&"").is_empty()
169+
{
170+
return Err(());
171+
}
172+
}
173+
}
161174
url.set_host_internal(host, None);
162175
Ok(())
163176
} else {
@@ -202,18 +215,19 @@ pub fn pathname(url: &Url) -> &str {
202215

203216
/// Setter for https://url.spec.whatwg.org/#dom-url-pathname
204217
pub fn set_pathname(url: &mut Url, new_pathname: &str) {
205-
if !url.cannot_be_a_base() && !new_pathname.is_empty() {
206-
if !SchemeType::from(url.scheme()).is_special()
218+
if url.cannot_be_a_base() {
219+
return;
220+
}
221+
if !SchemeType::from(url.scheme()).is_special()
207222
|| Some('/') == new_pathname.chars().nth(0)
208223
// \\ is a segment delimiter for 'special' URLs"
209224
|| Some('\\') == new_pathname.chars().nth(0)
210-
{
211-
url.set_path(new_pathname)
212-
} else {
213-
let mut path_to_set = String::from("/");
214-
path_to_set.push_str(new_pathname);
215-
url.set_path(&path_to_set)
216-
}
225+
{
226+
url.set_path(new_pathname)
227+
} else {
228+
let mut path_to_set = String::from("/");
229+
path_to_set.push_str(new_pathname);
230+
url.set_path(&path_to_set)
217231
}
218232
}
219233

0 commit comments

Comments
 (0)