From 8daa6ec4beaadcf5e65a4c1fafe456271786c98b Mon Sep 17 00:00:00 2001 From: Pascal Seitz Date: Wed, 1 Jul 2020 20:53:08 +0200 Subject: [PATCH] add more validations to safe decode --- src/block/decompress.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/block/decompress.rs b/src/block/decompress.rs index 3f2d03c..1d7c019 100644 --- a/src/block/decompress.rs +++ b/src/block/decompress.rs @@ -6,8 +6,8 @@ quick_error! { #[derive(Debug)] pub enum Error { /// Literal is out of bounds of the input - OutputTooSmall { - description("Output is too small for the decompressed data") + OutputTooSmall{expected_size:usize, actual_size:usize} { + display("Output ({:?}) is too small for the decompressed data, {:?}", actual_size, expected_size) } /// Literal is out of bounds of the input LiteralOutOfBounds { @@ -188,11 +188,12 @@ pub fn decompress_into(input: &[u8], output: &mut Vec) -> Result<(), Error> #[cfg(feature = "safe-decode")] { + // Check if literal is out of bounds for the input, and if there is enough space on the output if input.len() < input_pos + literal_length { return Err(Error::LiteralOutOfBounds); }; if output.len() < (output_ptr as usize - output_start + literal_length) { - return Err(Error::OutputTooSmall); + return Err(Error::OutputTooSmall{expected_size: (output_ptr as usize - output_start + literal_length), actual_size: output.len()}); }; } @@ -234,9 +235,13 @@ pub fn decompress_into(input: &[u8], output: &mut Vec) -> Result<(), Error> #[cfg(feature = "safe-decode")] { + // Check if literal is out of bounds for the input, and if there is enough space on the output if input.len() < input_pos + literal_length { return Err(Error::LiteralOutOfBounds); }; + if output.len() < (output_ptr as usize - output_start + literal_length) { + return Err(Error::OutputTooSmall{expected_size: (output_ptr as usize - output_start + literal_length), actual_size: output.len()}); + }; } unsafe { std::ptr::copy_nonoverlapping( @@ -261,6 +266,9 @@ pub fn decompress_into(input: &[u8], output: &mut Vec) -> Result<(), Error> if input_pos + 2 >= input.len() { return Err(Error::OffsetOutOfBounds); } + if input_pos + 2 >= output.len() { + return Err(Error::OffsetOutOfBounds); + } } let offset = read_u16(input, &mut input_pos); // Obtain the initial match length. The match length is the length of the duplicate segment