diff --git a/Cargo.toml b/Cargo.toml index 6328c50..3ec85ed 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "brotli" -version = "0.3.12" +version = "0.3.13" authors = ["Thomas Pickert "] license = "Apache-2.0" repository = "https://github.com/ende76/brotli-rs" diff --git a/README.md b/README.md index 47e5c68..7328ad0 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,11 @@ Compression provides a -struct to wrap a Brotli-compressed stream. A consu ## Changelog +###v0.3.12 -> v0.3.13 +---------------- + +Fixed uncaught non-positive distances. (Thanks, [Corey](https://github.com/frewsxcv)!). + ###v0.3.11 -> v0.3.12 ---------------- diff --git a/src/lib.rs b/src/lib.rs index cf5c197..ebf1d16 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -275,6 +275,7 @@ enum DecompressorError { InvalidLengthInStaticDictionary, InvalidMSkipLen, InvalidTransformId, + InvalidNonPositiveDistance, LessThanTwoNonZeroCodeLengths, NoCodeLength, NonZeroFillBit, @@ -311,6 +312,7 @@ impl Error for DecompressorError { DecompressorError::InvalidLengthInStaticDictionary => "Encountered invalid length in reference to static dictionary", DecompressorError::InvalidMSkipLen => "Most significant byte of MSKIPLEN was zero", DecompressorError::InvalidTransformId => "Encountered invalid transform id in reference to static dictionary", + DecompressorError::InvalidNonPositiveDistance => "Encountered invalid non-positive distance", DecompressorError::LessThanTwoNonZeroCodeLengths => "Encountered invalid complex prefix code with less than two non-zero codelengths", DecompressorError::NoCodeLength => "Encountered invalid complex prefix code with all zero codelengths", DecompressorError::NonZeroFillBit => "Enocuntered non-zero fill bit", @@ -1483,15 +1485,19 @@ impl Decompressor { }, Some(d @ 4...9) => { match (self.distance_buf.nth(0), 2 * (d as i64 % 2) - 1, (d - 2) >> 1) { - (Ok(distance), sign, d) => (*distance as i64 + (sign * d as i64)) as u32, + (Ok(distance), sign, d) => match *distance as i64 + (sign * d as i64) { + distance if distance <= 0 => return Err(DecompressorError::InvalidNonPositiveDistance), + distance => distance as u32 + }, (Err(_), _, _) => return Err(DecompressorError::RingBufferError), } }, // reference distance_buf here, to get the decoded distance Some(d @ 10...15) => { match (self.distance_buf.nth(1), 2 * (d as i64 % 2) - 1, (d - 8) >> 1) { - (Ok(distance), sign, d) => { - (*distance as i64 + (sign * d as i64)) as u32 + (Ok(distance), sign, d) => match *distance as i64 + (sign * d as i64) { + distance if distance <= 0 => return Err(DecompressorError::InvalidNonPositiveDistance), + distance => distance as u32 }, (Err(_), _, _) => return Err(DecompressorError::RingBufferError), } @@ -1533,7 +1539,7 @@ impl Decompressor { None => unreachable!(), // confirmed unreachable, distance_code is always set to Some(_) at this point }; - // debug(&format!("(dc, db, d) = {:?}", (self.meta_block.distance_code, self.distance_buf.clone(), distance))); + // println!("(dc, db, d) = {:?}", (self.meta_block.distance_code, self.distance_buf.clone(), distance)); if self.meta_block.distance_code.unwrap() > 0 && distance as usize <= cmp::min(self.header.window_size.unwrap(), self.count_output) { self.distance_buf.push(distance); diff --git a/src/main.rs b/src/main.rs index 1bccfa5..2e96499 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,7 +5,5 @@ use brotli::Decompressor; fn main() { let mut input = vec![]; - let _ = Decompressor::new(&b"\x1b\x3f\x01\xf0\x24\xb0\xc2\xa4\x80\x54\xff\xd7\x24\xb0\x12".to_vec() as &[u8]).read_to_end(&mut input); - - println!("{:?}", String::from_utf8(input)); + let _ = Decompressor::new(&b"\x5b\xff\x00\x01\x40\x0a\x00\xab\x16\x7b\xac\x14\x48\x4e\x73\xed\x01\x92\x03".to_vec() as &[u8]).read_to_end(&mut input); } \ No newline at end of file diff --git a/tests/lib.rs b/tests/lib.rs index 9e1b886..f90ddce 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -443,6 +443,18 @@ fn should_decompress_to_string_frewsxcv_08() { assert_eq!(vec![88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 32, 216, 131, 217, 170, 216, 135, 217, 165, 61, 39, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 32, 1, 0, 0, 0, 3, 0, 0, 0, 61, 39, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88], input); } +#[test] +/// frewsxcv: fuzzer-test +/// exposes uncaught non-positive distances +/// found and reported by Corey Farwell – https://github.com/ende76/brotli-rs/issues/10 +fn should_decompress_frewsxcv_09() { + use std::io::Read; + use brotli::Decompressor; + + let mut input = vec![]; + let _ = Decompressor::new(&b"\x5b\xff\x00\x01\x40\x0a\x00\xab\x16\x7b\xac\x14\x48\x4e\x73\xed\x01\x92\x03".to_vec() as &[u8]).read_to_end(&mut input); +} + fn inverse_move_to_front_transform(v: &mut[u8]) { let mut mtf: Vec = vec![0; 256]; let v_len = v.len();