diff --git a/src/deflate/deflater.rs b/src/deflate/deflater.rs index 93dbd43f..c6b0d35a 100644 --- a/src/deflate/deflater.rs +++ b/src/deflate/deflater.rs @@ -1,6 +1,6 @@ use crate::atomicmin::AtomicMin; use crate::{PngError, PngResult}; -use libdeflater::{CompressionError, CompressionLvl, Compressor}; +use libdeflater::*; pub fn deflate(data: &[u8], level: u8, max_size: &AtomicMin) -> PngResult> { let mut compressor = Compressor::new(CompressionLvl::new(level.into()).unwrap()); @@ -23,3 +23,16 @@ pub fn deflate(data: &[u8], level: u8, max_size: &AtomicMin) -> PngResult PngResult> { + let mut decompressor = Decompressor::new(); + let mut dest = vec![0; out_size]; + let len = decompressor + .zlib_decompress(data, &mut dest) + .map_err(|err| match err { + DecompressionError::BadData => PngError::InvalidData, + DecompressionError::InsufficientSpace => PngError::new("inflated data too long"), + })?; + dest.truncate(len); + Ok(dest) +} diff --git a/src/deflate/mod.rs b/src/deflate/mod.rs index 0c109f96..59ace7ef 100644 --- a/src/deflate/mod.rs +++ b/src/deflate/mod.rs @@ -14,6 +14,8 @@ pub mod miniz_stream; mod deflater; #[cfg(feature = "libdeflater")] pub use deflater::deflate as libdeflater_deflate; +#[cfg(feature = "libdeflater")] +pub use deflater::inflate as libdeflater_inflate; #[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))] pub mod cfzlib; diff --git a/src/lib.rs b/src/lib.rs index 4057398d..af152183 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,7 +26,7 @@ mod rayon; use crate::atomicmin::AtomicMin; use crate::colors::BitDepth; -use crate::deflate::inflate; +use crate::deflate::libdeflater_inflate; use crate::evaluate::Evaluator; use crate::png::PngData; use crate::png::PngImage; @@ -948,7 +948,9 @@ fn srgb_rendering_intent(mut iccp: &[u8]) -> Option { if compression_method != 0 { return None; // The profile is supposed to be compressed (method 0) } - let icc_data = inflate(compressed_data).ok()?; + // The decompressed size is unknown so we have to guess the required buffer size + let max_size = (compressed_data.len() * 2).max(1000); + let icc_data = libdeflater_inflate(compressed_data, max_size).ok()?; let rendering_intent = *icc_data.get(67)?; diff --git a/src/png/mod.rs b/src/png/mod.rs index d0da5527..846269f3 100644 --- a/src/png/mod.rs +++ b/src/png/mod.rs @@ -112,7 +112,7 @@ impl PngData { None => return Err(PngError::ChunkMissing("IHDR")), }; let ihdr_header = parse_ihdr_header(&ihdr)?; - let raw_data = deflate::inflate(idat_headers.as_ref())?; + let raw_data = deflate::libdeflater_inflate(idat_headers.as_ref(), ihdr_header.raw_data_size())?; // Reject files with incorrect width/height or truncated data if raw_data.len() != ihdr_header.raw_data_size() {