diff --git a/src/lib.rs b/src/lib.rs index 89e08c3c2..8c8536a45 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -998,12 +998,18 @@ impl Url { } if let Some(host) = host { + if host == "" && SchemeType::from(self.scheme()).is_special() { + return Err(ParseError::EmptyHost); + } self.set_host_internal(try!(Host::parse(host)), None) } else if self.has_host() { + if SchemeType::from(self.scheme()).is_special() { + return Err(ParseError::EmptyHost) + } debug_assert!(self.byte_at(self.scheme_end) == b':'); debug_assert!(self.byte_at(self.path_start) == b'/'); let new_path_start = self.scheme_end + 1; - self.serialization.drain(self.path_start as usize..new_path_start as usize); + self.serialization.drain(new_path_start as usize..self.path_start as usize); let offset = self.path_start - new_path_start; self.path_start = new_path_start; self.username_end = new_path_start; diff --git a/tests/unit.rs b/tests/unit.rs index eb460015d..b4d1992dd 100644 --- a/tests/unit.rs +++ b/tests/unit.rs @@ -317,3 +317,19 @@ fn append_empty_segment_then_mutate() { url.assert_invariants(); assert_eq!(url.to_string(), "http://localhost:6767/foo/bar?a=b"); } + +#[test] +/// https://github.com/servo/rust-url/issues/243 +fn test_set_host() { + let mut url = Url::parse("https://example.net/hello").unwrap(); + url.set_host(Some("foo.com")).unwrap(); + assert_eq!(url.as_str(), "https://foo.com/hello"); + assert!(url.set_host(None).is_err()); + assert_eq!(url.as_str(), "https://foo.com/hello"); + assert!(url.set_host(Some("")).is_err()); + assert_eq!(url.as_str(), "https://foo.com/hello"); + + let mut url = Url::parse("foobar://example.net/hello").unwrap(); + url.set_host(None).unwrap(); + assert_eq!(url.as_str(), "foobar:/hello"); +}