fix(headers): prevent 2 panics in QualityItem parsing

1. index out of bounds if semicolon is the last character
2. not a char boundary on non-ASCII input (only allow ASCII now)

Bugs found using `cargo fuzz`
This commit is contained in:
Pyfisch
2017-03-05 12:26:19 +01:00
parent c51a9993fa
commit d80aae55b1
2 changed files with 18 additions and 0 deletions

View File

@@ -114,6 +114,11 @@ header! {
SubLevel::Plain, vec![(Attr::Charset, Value::Utf8)]),
Quality(500)),
])));
test_header!(
test_fuzzing1,
vec![b"chunk#;e"],
None
);
}
}

View File

@@ -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())
}
}