From b93777c2373e106c58291339dcc010c2337785f2 Mon Sep 17 00:00:00 2001 From: Sophie Herold Date: Sun, 26 Nov 2023 08:41:14 +0100 Subject: [PATCH] Option to ignore ancillary chunks with invalid CRC (#430) Skipping non-critical chunks if the CRC check fails is the default it libpng. Therefore adding this option and enabling it by default. image-rs/image#2057 --- src/decoder/stream.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/decoder/stream.rs b/src/decoder/stream.rs index 9f4b4dd7..469b4518 100644 --- a/src/decoder/stream.rs +++ b/src/decoder/stream.rs @@ -385,6 +385,7 @@ pub struct DecodeOptions { ignore_adler32: bool, ignore_crc: bool, ignore_text_chunk: bool, + skip_ancillary_crc_failures: bool, } impl Default for DecodeOptions { @@ -393,6 +394,7 @@ impl Default for DecodeOptions { ignore_adler32: true, ignore_crc: false, ignore_text_chunk: false, + skip_ancillary_crc_failures: true, } } } @@ -425,6 +427,13 @@ impl DecodeOptions { pub fn set_ignore_text_chunk(&mut self, ignore_text_chunk: bool) { self.ignore_text_chunk = ignore_text_chunk; } + + /// Ignore ancillary chunks if CRC fails + /// + /// Defaults to `true` + pub fn set_skip_ancillary_crc_failures(&mut self, skip_ancillary_crc_failures: bool) { + self.skip_ancillary_crc_failures = skip_ancillary_crc_failures; + } } /// PNG StreamingDecoder (low-level interface) @@ -530,6 +539,14 @@ impl StreamingDecoder { self.decode_options.set_ignore_crc(ignore_crc) } + /// Ignore ancillary chunks if CRC fails + /// + /// Defaults to `true` + pub fn set_skip_ancillary_crc_failures(&mut self, skip_ancillary_crc_failures: bool) { + self.decode_options + .set_skip_ancillary_crc_failures(skip_ancillary_crc_failures) + } + /// Low level StreamingDecoder interface. /// /// Allows to stream partial data to the encoder. Returns a tuple containing the bytes that have @@ -647,6 +664,12 @@ impl StreamingDecoder { } else { Ok((1, Decoded::ChunkComplete(val, type_str))) } + } else if self.decode_options.skip_ancillary_crc_failures + && !chunk::is_critical(type_str) + { + // Ignore ancillary chunk with invalid CRC + self.state = Some(State::U32(U32ValueKind::Length)); + Ok((1, Decoded::Nothing)) } else { Err(DecodingError::Format( FormatErrorInner::CrcMismatch {