Merge pull request #1084 from pyfisch/fuzzing
[WIP] fix bugs in header field parsers
This commit is contained in:
		| @@ -114,6 +114,13 @@ header! { | ||||
|                     SubLevel::Plain, vec![(Attr::Charset, Value::Utf8)]), | ||||
|                     Quality(500)), | ||||
|             ]))); | ||||
|  | ||||
|         #[test] | ||||
|         fn test_fuzzing1() { | ||||
|             let raw: Raw = "chunk#;e".into(); | ||||
|             let header = Accept::parse_header(&raw); | ||||
|             assert!(header.is_ok()); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -83,6 +83,9 @@ header! { | ||||
|         test_header!(test14, | ||||
|             vec![b"matched-\"dquotes\""], | ||||
|             None::<ETag>); | ||||
|         test_header!(test15, | ||||
|             vec![b"\""], | ||||
|             None::<ETag>); | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -123,15 +123,17 @@ impl FromStr for EntityTag { | ||||
|         let length: usize = s.len(); | ||||
|         let slice = &s[..]; | ||||
|         // Early exits if it doesn't terminate in a DQUOTE. | ||||
|         if !slice.ends_with('"') { | ||||
|         if !slice.ends_with('"') || slice.len() < 2 { | ||||
|             return Err(::Error::Header); | ||||
|         } | ||||
|         // The etag is weak if its first char is not a DQUOTE. | ||||
|         if slice.starts_with('"') && check_slice_validity(&slice[1..length-1]) { | ||||
|         if slice.len() >= 2 && slice.starts_with('"') | ||||
|                 && check_slice_validity(&slice[1..length-1]) { | ||||
|             // No need to check if the last char is a DQUOTE, | ||||
|             // we already did that above. | ||||
|             return Ok(EntityTag { weak: false, tag: slice[1..length-1].to_owned() }); | ||||
|         } else if slice.starts_with("W/\"") && check_slice_validity(&slice[3..length-1]) { | ||||
|         } else if slice.len() >= 4 && slice.starts_with("W/\"") | ||||
|                 && check_slice_validity(&slice[3..length-1]) { | ||||
|             return Ok(EntityTag { weak: true, tag: slice[3..length-1].to_owned() }); | ||||
|         } | ||||
|         Err(::Error::Header) | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| use std::ascii::AsciiExt; | ||||
| use std::cmp; | ||||
| use std::default::Default; | ||||
| use std::fmt; | ||||
| @@ -73,12 +74,18 @@ impl<T: fmt::Display> fmt::Display for QualityItem<T> { | ||||
| impl<T: str::FromStr> str::FromStr for QualityItem<T> { | ||||
|     type Err = ::Error; | ||||
|     fn from_str(s: &str) -> ::Result<QualityItem<T>> { | ||||
|         if !s.is_ascii() { | ||||
|             return Err(::Error::Header); | ||||
|         } | ||||
|         // Set defaults used if parsing fails. | ||||
|         let mut raw_item = s; | ||||
|         let mut quality = 1f32; | ||||
|  | ||||
|         let parts: Vec<&str> = s.rsplitn(2, ';').map(|x| x.trim()).collect(); | ||||
|         if parts.len() == 2 { | ||||
|             if parts[0].len() < 2 { | ||||
|                 return Err(::Error::Header); | ||||
|             } | ||||
|             let start = &parts[0][0..2]; | ||||
|             if start == "q=" || start == "Q=" { | ||||
|                 let q_part = &parts[0][2..parts[0].len()]; | ||||
| @@ -212,4 +219,10 @@ mod tests { | ||||
|     fn test_quality_invalid2() { | ||||
|         q(2.0); | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
|     fn test_fuzzing_bugs() { | ||||
|         assert!("99999;".parse::<QualityItem<String>>().is_err()); | ||||
|         assert!("\x0d;;;=\u{d6aa}==".parse::<QualityItem<String>>().is_err()) | ||||
|     } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user