diff --git a/src/decoder/mod.rs b/src/decoder/mod.rs index dc05d37..12a11e5 100644 --- a/src/decoder/mod.rs +++ b/src/decoder/mod.rs @@ -1116,6 +1116,7 @@ impl Decoder { length, buffer.len(), buffer.byte_len(), + self.limits.intermediate_buffer_size, )?; // Read into output buffer. @@ -1180,6 +1181,7 @@ impl Decoder { compressed_length, tile_samples, byte_len, + self.limits.intermediate_buffer_size, )?; for row in 0..(tile_length - padding_down) { @@ -1224,17 +1226,20 @@ impl Decoder { compressed_length: u64, samples: usize, // Expected chunk length in samples byte_len: usize, // Byte length of the samples in result buffer + intermediate_buffer_size: usize, ) -> TiffResult> { Ok(match compression_method { CompressionMethod::None => Box::new(reader), - CompressionMethod::LZW => Box::new( - LZWReader::new( - reader, - usize::try_from(compressed_length)?, - samples * byte_len, - )? - .1, - ), + CompressionMethod::LZW => { + let clen = usize::try_from(compressed_length)?; + + if samples * byte_len > intermediate_buffer_size || clen > intermediate_buffer_size + { + return Err(TiffError::LimitsExceeded); + } + + Box::new(LZWReader::new(reader, clen, samples * byte_len)?.1) + } CompressionMethod::PackBits => { Box::new(PackBitsReader::new(reader, usize::try_from(compressed_length)?)?.1) } diff --git a/tests/decode_images.rs b/tests/decode_images.rs index d2e8543..33dc9b5 100644 --- a/tests/decode_images.rs +++ b/tests/decode_images.rs @@ -404,3 +404,22 @@ fn oom() { unexpected => panic!("Unexpected error {}", unexpected), } } + +#[test] +fn oom_2() { + let image = [ + 73, 73, 42, 0, 8, 0, 0, 0, 8, 0, 0, 1, 4, 0, 1, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 40, 1, 0, 0, + 0, 158, 0, 0, 251, 3, 1, 3, 0, 1, 0, 0, 0, 5, 0, 0, 0, 6, 1, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 17, 1, 4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 3, 0, 1, 0, 0, 0, 3, 128, 0, 0, 22, 1, 4, 0, 1, + 0, 0, 0, 40, 0, 0, 0, 23, 1, 4, 0, 1, 0, 0, 0, 48, 178, 178, 178, 0, 1, 0, 13, 13, + ]; + + let mut decoder = tiff::decoder::Decoder::new(std::io::Cursor::new(&image)).unwrap(); + + let err = decoder.read_image().unwrap_err(); + + match err { + tiff::TiffError::LimitsExceeded => {} + unexpected => panic!("Unexpected error {}", unexpected), + } +}