From 3071fdb3dacdd8f153e34f10b62f502fa312803e Mon Sep 17 00:00:00 2001 From: Ende Date: Mon, 26 Oct 2015 14:37:31 -0400 Subject: [PATCH] FIX: invalid block type in block switch command #12 --- Cargo.toml | 2 +- src/lib.rs | 17 +++++++++++++---- src/main.rs | 4 +--- tests/lib.rs | 18 ++++++++++++++++++ 4 files changed, 33 insertions(+), 8 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3ec85ed..0ad2711 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "brotli" -version = "0.3.13" +version = "0.3.14" authors = ["Thomas Pickert "] license = "Apache-2.0" repository = "https://github.com/ende76/brotli-rs" diff --git a/src/lib.rs b/src/lib.rs index ebf1d16..2e673da 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -270,6 +270,7 @@ enum DecompressorError { ExceededExpectedBytes, InvalidBlockCountCode, InvalidBlockSwitchCommandCode, + InvalidBlockType, InvalidBlockTypeCode, InvalidInsertAndCopyLengthCode, InvalidLengthInStaticDictionary, @@ -307,6 +308,7 @@ impl Error for DecompressorError { DecompressorError::ExceededExpectedBytes => "More uncompressed bytes than expected in meta-block", DecompressorError::InvalidBlockCountCode => "Encountered invalid value for block count code", DecompressorError::InvalidBlockSwitchCommandCode => "Encountered invalid value for block switch command code", + DecompressorError::InvalidBlockType => "Encountered invalid value for block type", DecompressorError::InvalidBlockTypeCode => "Encountered invalid value for block type code", DecompressorError::InvalidInsertAndCopyLengthCode => "Encountered invalid value for insert-and-copy-length code", DecompressorError::InvalidLengthInStaticDictionary => "Encountered invalid length in reference to static dictionary", @@ -1301,8 +1303,6 @@ impl Decompressor { Err(_) => return Err(DecompressorError::UnexpectedEOF), }; - // debug(&format!("switch block type code = {:?}", block_type_code)); - let block_type = match block_type_code { 0 => btype_prev, 1 => (btype + 1) % n_bltypes, @@ -1310,6 +1310,10 @@ impl Decompressor { _ => return Err(DecompressorError::InvalidBlockTypeCode), }; + if block_type >= n_bltypes { + return Err(DecompressorError::InvalidBlockType); + } + // debug(&format!("block type = {:?}", block_type)); let block_count = match self.parse_block_count(&prefix_tree_counts) { @@ -1379,6 +1383,9 @@ impl Decompressor { }; let btype = self.meta_block.btype_l as usize; + + // println!("btype = {:?}", btype); + let context_mode = self.meta_block.context_modes_literals.as_ref().unwrap()[btype]; // debug(&format!("[p1, p2] = {:?}", self.literal_buf)); @@ -1410,13 +1417,15 @@ impl Decompressor { _ => unreachable!(), // confirmed unreachable, context_mode is always read from two bits }; - // debug(&format!("(btype, cid) = {:?}", (btype, cid))); + // println!("(btype, cid) = {:?}", (btype, cid)); let index = self.meta_block.header.c_map_l.as_ref().unwrap()[btype * 64 + cid] as usize; // debug(&format!("global bit pos = {:?}", self.in_stream.global_bit_pos)); - // debug(&format!("literal prefix code index = {:?}", index)); + // println!("literal prefix code index = {:?}", index); + + *lit = match self.meta_block.prefix_trees_literals.as_ref().unwrap()[index].lookup_symbol(&mut self.in_stream) { Ok(Some(symbol)) => symbol as Literal, diff --git a/src/main.rs b/src/main.rs index 305c151..6467f96 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,7 +5,5 @@ use brotli::Decompressor; fn main() { let mut input = vec![]; - let result = 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); - - println!("{:?}", result); + let _ = Decompressor::new(&b"\x51\xac\x00\x48\x2f\x73\x14\x01\x14\x00\x00\x01\x00\x14\x14\xff\x00\x02\x00\x00\x00\x00\x00\x64\x14\x24\x14\x14\x14\x14\x14\x80\x00\x00\x14\xff\xff\x00\x00\x14\x14\x14\x14\x14\x14\x80\x00\x80".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 c5056cc..52c27b1 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -477,6 +477,24 @@ fn should_reject_frewsxcv_09() { } } +#[test] +#[should_panic(expected="invalid value for block type")] +/// frewsxcv: fuzzer-test +/// exposes uncaught invalid block type in block switch command +/// found and reported by Corey Farwell – https://github.com/ende76/brotli-rs/issues/10 +fn should_reject_frewsxcv_10() { + use std::io::Read; + use brotli::Decompressor; + + let mut input = vec![]; + let result = Decompressor::new(&b"\x51\xac\x00\x48\x2f\x73\x14\x01\x14\x00\x00\x01\x00\x14\x14\xff\x00\x02\x00\x00\x00\x00\x00\x64\x14\x24\x14\x14\x14\x14\x14\x80\x00\x00\x14\xff\xff\x00\x00\x14\x14\x14\x14\x14\x14\x80\x00\x80".to_vec() as &[u8]).read_to_end(&mut input); + + match result { + Err(e) => panic!("{:?}", e), + _ => {}, + } +} + fn inverse_move_to_front_transform(v: &mut[u8]) { let mut mtf: Vec = vec![0; 256]; let v_len = v.len();