From 01ec217a829f41b63a2ee746980746251c806abd Mon Sep 17 00:00:00 2001 From: Daniel Lockyer Date: Wed, 19 Apr 2017 19:39:26 +0100 Subject: [PATCH 1/6] Remove lifetimes --- src/form_urlencoded.rs | 2 +- src/parser.rs | 8 ++++---- src/percent_encoding.rs | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/form_urlencoded.rs b/src/form_urlencoded.rs index bfe4fbff..c53acfde 100644 --- a/src/form_urlencoded.rs +++ b/src/form_urlencoded.rs @@ -121,7 +121,7 @@ fn decode(input: &[u8], encoding: EncodingOverride) -> Cow { } /// Replace b'+' with b' ' -fn replace_plus<'a>(input: &'a [u8]) -> Cow<'a, [u8]> { +fn replace_plus(input: &[u8]) -> Cow<[u8]> { match input.iter().position(|&b| b == b'+') { None => Cow::Borrowed(input), Some(first_position) => { diff --git a/src/parser.rs b/src/parser.rs index e01fad9d..5df8b302 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -736,8 +736,8 @@ impl<'a> Parser<'a> { Ok((host_end, host.into(), port, remaining)) } - pub fn parse_host<'i>(mut input: Input<'i>, scheme_type: SchemeType) - -> ParseResult<(Host, Input<'i>)> { + pub fn parse_host(mut input: Input, scheme_type: SchemeType) + -> ParseResult<(Host, Input)> { // Undo the Input abstraction here to avoid allocating in the common case // where the host part of the input does not contain any tab or newline let input_str = input.chars.as_str(); @@ -830,9 +830,9 @@ impl<'a> Parser<'a> { Ok((true, host, remaining)) } - pub fn parse_port<'i, P>(mut input: Input<'i>, default_port: P, + pub fn parse_port

(mut input: Input, default_port: P, context: Context) - -> ParseResult<(Option, Input<'i>)> + -> ParseResult<(Option, Input)> where P: Fn() -> Option { let mut port: u32 = 0; let mut has_any_digit = false; diff --git a/src/percent_encoding.rs b/src/percent_encoding.rs index 8a621ffe..64ed757d 100644 --- a/src/percent_encoding.rs +++ b/src/percent_encoding.rs @@ -242,7 +242,7 @@ impl<'a, E: EncodeSet> From> for Cow<'a, str> { /// (which returns `Cow::Borrowed` when `input` contains no percent-encoded sequence) /// and has `decode_utf8()` and `decode_utf8_lossy()` methods. #[inline] -pub fn percent_decode<'a>(input: &'a [u8]) -> PercentDecode<'a> { +pub fn percent_decode(input: &[u8]) -> PercentDecode { PercentDecode { bytes: input.iter() } From 844e2d5cf8484d8213d0cdf375dc47fbbd10e762 Mon Sep 17 00:00:00 2001 From: Daniel Lockyer Date: Wed, 19 Apr 2017 19:40:16 +0100 Subject: [PATCH 2/6] Switch double-quotes to single-quotes --- src/host.rs | 8 ++++---- src/parser.rs | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/host.rs b/src/host.rs index 50488772..1c905f97 100644 --- a/src/host.rs +++ b/src/host.rs @@ -139,8 +139,8 @@ impl Host { /// /// https://url.spec.whatwg.org/#host-parsing pub fn parse(input: &str) -> Result { - if input.starts_with("[") { - if !input.ends_with("]") { + if input.starts_with('[') { + if !input.ends_with(']') { return Err(ParseError::InvalidIpv6Address) } return parse_ipv6addr(&input[1..input.len() - 1]).map(Host::Ipv6) @@ -304,14 +304,14 @@ fn parse_ipv4number(mut input: &str) -> Result { if input.starts_with("0x") || input.starts_with("0X") { input = &input[2..]; r = 16; - } else if input.len() >= 2 && input.starts_with("0") { + } else if input.len() >= 2 && input.starts_with('0') { input = &input[1..]; r = 8; } if input.is_empty() { return Ok(0); } - if input.starts_with("+") { + if input.starts_with('+') { return Err(()) } match u32::from_str_radix(&input, r) { diff --git a/src/parser.rs b/src/parser.rs index 5df8b302..dfe1653f 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -878,7 +878,7 @@ impl<'a> Parser<'a> { path_start: usize, mut input: Input<'i>) -> Input<'i> { // Relative path state - debug_assert!(self.serialization.ends_with("/")); + debug_assert!(self.serialization.ends_with('/')); loop { let segment_start = self.serialization.len(); let mut ends_with_slash = false; @@ -926,7 +926,7 @@ impl<'a> Parser<'a> { debug_assert!(self.serialization.as_bytes()[segment_start - 1] == b'/'); self.serialization.truncate(segment_start - 1); // Truncate "/.." self.pop_path(scheme_type, path_start); - if !self.serialization[path_start..].ends_with("/") { + if !self.serialization[path_start..].ends_with('/') { self.serialization.push('/') } }, From 3c21bd965066ed80e4a6e2efa7e2ef9569617545 Mon Sep 17 00:00:00 2001 From: Daniel Lockyer Date: Wed, 19 Apr 2017 19:41:05 +0100 Subject: [PATCH 3/6] Use nice helper functions --- src/host.rs | 4 +--- src/parser.rs | 2 +- src/percent_encoding.rs | 2 +- tests/unit.rs | 4 ++-- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/host.rs b/src/host.rs index 1c905f97..b2afd6cf 100644 --- a/src/host.rs +++ b/src/host.rs @@ -477,9 +477,7 @@ fn parse_ipv6addr(input: &str) -> ParseResult { let mut swaps = piece_pointer - compress_pointer; piece_pointer = 7; while swaps > 0 { - let tmp = pieces[piece_pointer]; - pieces[piece_pointer] = pieces[compress_pointer + swaps - 1]; - pieces[compress_pointer + swaps - 1] = tmp; + pieces.swap(piece_pointer, compress_pointer + swaps - 1); swaps -= 1; piece_pointer -= 1; } diff --git a/src/parser.rs b/src/parser.rs index dfe1653f..4b8c17d3 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -209,7 +209,7 @@ impl bool> Pattern for F { impl<'i> Iterator for Input<'i> { type Item = char; fn next(&mut self) -> Option { - self.chars.by_ref().filter(|&c| !matches!(c, '\t' | '\n' | '\r')).next() + self.chars.by_ref().find(|&c| !matches!(c, '\t' | '\n' | '\r')) } } diff --git a/src/percent_encoding.rs b/src/percent_encoding.rs index 64ed757d..90891a62 100644 --- a/src/percent_encoding.rs +++ b/src/percent_encoding.rs @@ -298,7 +298,7 @@ impl<'a> PercentDecode<'a> { /// If the percent-decoding is different from the input, return it as a new bytes vector. pub fn if_any(&self) -> Option> { let mut bytes_iter = self.bytes.clone(); - while bytes_iter.find(|&&b| b == b'%').is_some() { + while bytes_iter.any(|&b| b == b'%') { if let Some(decoded_byte) = after_percent_sign(&mut bytes_iter) { let initial_bytes = self.bytes.as_slice(); let unchanged_bytes_len = initial_bytes.len() - bytes_iter.len() - 3; diff --git a/tests/unit.rs b/tests/unit.rs index 2d13340b..c2aa93ab 100644 --- a/tests/unit.rs +++ b/tests/unit.rs @@ -164,12 +164,12 @@ fn test_equality() { // Different scheme let a: Url = url("http://example.com/"); let b: Url = url("https://example.com/"); - assert!(a != b); + assert_ne!(a, b); // Different host let a: Url = url("http://foo.com/"); let b: Url = url("http://bar.com/"); - assert!(a != b); + assert_ne!(a, b); // Missing path, automatically substituted. Semantically the same. let a: Url = url("http://foo.com"); From 6db4c409e337c0b555e5d12ce44e5cd59ededb69 Mon Sep 17 00:00:00 2001 From: Daniel Lockyer Date: Wed, 19 Apr 2017 19:41:24 +0100 Subject: [PATCH 4/6] Tidy up some small nits --- src/host.rs | 2 +- src/parser.rs | 4 ++-- tests/data.rs | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/host.rs b/src/host.rs index b2afd6cf..2cb6c970 100644 --- a/src/host.rs +++ b/src/host.rs @@ -314,7 +314,7 @@ fn parse_ipv4number(mut input: &str) -> Result { if input.starts_with('+') { return Err(()) } - match u32::from_str_radix(&input, r) { + match u32::from_str_radix(input, r) { Ok(number) => Ok(number), Err(_) => Err(()), } diff --git a/src/parser.rs b/src/parser.rs index 4b8c17d3..8b019bb4 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -854,7 +854,7 @@ impl<'a> Parser<'a> { if !has_any_digit || opt_port == default_port() { opt_port = None; } - return Ok((opt_port, input)) + Ok((opt_port, input)) } pub fn parse_path_start<'i>(&mut self, scheme_type: SchemeType, has_host: &mut bool, @@ -1030,7 +1030,7 @@ impl<'a> Parser<'a> { } } None => return Ok((None, None)), - _ => panic!("Programming error. parse_query_and_fragment() called without ? or # {:?}") + _ => panic!("Programming error. parse_query_and_fragment() called without ? or #") } let fragment_start = to_u32(self.serialization.len())?; diff --git a/tests/data.rs b/tests/data.rs index 179d4f4d..dba8f197 100644 --- a/tests/data.rs +++ b/tests/data.rs @@ -26,7 +26,7 @@ fn check_invariants(url: &Url) { } -fn run_parsing(input: String, base: String, expected: Result) { +fn run_parsing(input: &String, base: &String, expected: Result) { let base = match Url::parse(&base) { Ok(base) => base, Err(message) => panic!("Error parsing base {:?}: {}", base, message) @@ -135,7 +135,7 @@ fn collect_parsing(add_test: &mut F) { }) }; add_test(format!("{:?} @ base {:?}", input, base), - test::TestFn::dyn_test_fn(move || run_parsing(input, base, expected))); + test::TestFn::dyn_test_fn(move || run_parsing(&input, &base, expected))); } } From 249369a528c1a93c41163e44c92d49fe0d8a95fa Mon Sep 17 00:00:00 2001 From: Daniel Lockyer Date: Wed, 19 Apr 2017 19:45:06 +0100 Subject: [PATCH 5/6] Updating fuzzing code to latest format --- fuzz/.gitignore | 3 ++- fuzz/Cargo.toml | 6 ++++++ fuzz/fuzzers/parse.rs | 18 ++++++------------ 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/fuzz/.gitignore b/fuzz/.gitignore index 08ba2bbe..572e03bd 100644 --- a/fuzz/.gitignore +++ b/fuzz/.gitignore @@ -1,3 +1,4 @@ target -libfuzzer +corpus +artifacts diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index 0443d5ed..0b108b95 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -3,9 +3,15 @@ name = "url-fuzz" version = "0.0.1" authors = ["Automatically generated"] +publish = false + +[package.metadata] +cargo-fuzz = true [dependencies.url] path = ".." +[dependencies.libfuzzer-sys] +git = "https://github.com/rust-fuzz/libfuzzer-sys.git" [[bin]] name = "parse" diff --git a/fuzz/fuzzers/parse.rs b/fuzz/fuzzers/parse.rs index f9ff8e37..ef8c53f4 100644 --- a/fuzz/fuzzers/parse.rs +++ b/fuzz/fuzzers/parse.rs @@ -1,16 +1,10 @@ #![no_main] - -extern crate libfuzzer_sys; - +#[macro_use] extern crate libfuzzer_sys; extern crate url; -use std::slice; use std::str; -#[export_name="LLVMFuzzerTestOneInput"] -pub extern fn go(data: *const u8, size: isize) -> i32 { - let slice = unsafe { slice::from_raw_parts(data, size as usize) }; - if let Ok(utf8) = str::from_utf8(slice) { - let url = url::Url::parse(utf8); - } - return 0; -} +fuzz_target!(|data: &[u8]| { + if let Ok(utf8) = str::from_utf8(data) { + let _ = url::Url::parse(utf8); + } +}); From f34fa8fd378f6f6c801e6da3e7de157a2cfb1f1f Mon Sep 17 00:00:00 2001 From: Daniel Lockyer Date: Fri, 12 May 2017 09:09:07 +0100 Subject: [PATCH 6/6] Switch from &String to &str --- tests/data.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/data.rs b/tests/data.rs index dba8f197..a116df8c 100644 --- a/tests/data.rs +++ b/tests/data.rs @@ -26,7 +26,7 @@ fn check_invariants(url: &Url) { } -fn run_parsing(input: &String, base: &String, expected: Result) { +fn run_parsing(input: &str, base: &str, expected: Result) { let base = match Url::parse(&base) { Ok(base) => base, Err(message) => panic!("Error parsing base {:?}: {}", base, message)