diff --git a/src/header/common/accept.rs b/src/header/common/accept.rs index f58a143855..5b38ded158 100644 --- a/src/header/common/accept.rs +++ b/src/header/common/accept.rs @@ -114,6 +114,11 @@ header! { SubLevel::Plain, vec![(Attr::Charset, Value::Utf8)]), Quality(500)), ]))); + test_header!( + test_fuzzing1, + vec![b"chunk#;e"], + None + ); } } diff --git a/src/header/shared/quality_item.rs b/src/header/shared/quality_item.rs index e3cb7a27e4..497df37a0d 100644 --- a/src/header/shared/quality_item.rs +++ b/src/header/shared/quality_item.rs @@ -1,3 +1,4 @@ +use std::ascii::AsciiExt; use std::cmp; use std::default::Default; use std::fmt; @@ -73,12 +74,18 @@ impl fmt::Display for QualityItem { impl str::FromStr for QualityItem { type Err = ::Error; fn from_str(s: &str) -> ::Result> { + 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::>().is_err()); + assert!("\x0d;;;=\u{d6aa}==".parse::>().is_err()) + } }