png/decoder/
stream.rs

1use std::convert::TryInto;
2use std::error;
3use std::fmt;
4use std::io;
5use std::{borrow::Cow, cmp::min};
6
7use crc32fast::Hasher as Crc32;
8
9use super::zlib::ZlibStream;
10use crate::chunk::{self, ChunkType, IDAT, IEND, IHDR};
11use crate::common::{
12    AnimationControl, BitDepth, BlendOp, ColorType, DisposeOp, FrameControl, Info, ParameterError,
13    PixelDimensions, ScaledFloat, SourceChromaticities, Unit,
14};
15use crate::text_metadata::{ITXtChunk, TEXtChunk, TextDecodingError, ZTXtChunk};
16use crate::traits::ReadBytesExt;
17use crate::Limits;
18
19/// TODO check if these size are reasonable
20pub const CHUNK_BUFFER_SIZE: usize = 32 * 1024;
21
22/// Determines if checksum checks should be disabled globally.
23///
24/// This is used only in fuzzing. `afl` automatically adds `--cfg fuzzing` to RUSTFLAGS which can
25/// be used to detect that build.
26const CHECKSUM_DISABLED: bool = cfg!(fuzzing);
27
28/// Kind of `u32` value that is being read via `State::U32`.
29#[derive(Debug)]
30enum U32ValueKind {
31    /// First 4 bytes of the PNG signature - see
32    /// http://www.libpng.org/pub/png/spec/1.2/PNG-Structure.html#PNG-file-signature
33    Signature1stU32,
34    /// Second 4 bytes of the PNG signature - see
35    /// http://www.libpng.org/pub/png/spec/1.2/PNG-Structure.html#PNG-file-signature
36    Signature2ndU32,
37    /// Chunk length - see
38    /// http://www.libpng.org/pub/png/spec/1.2/PNG-Structure.html#Chunk-layout
39    Length,
40    /// Chunk type - see
41    /// http://www.libpng.org/pub/png/spec/1.2/PNG-Structure.html#Chunk-layout
42    Type { length: u32 },
43    /// Chunk checksum - see
44    /// http://www.libpng.org/pub/png/spec/1.2/PNG-Structure.html#Chunk-layout
45    Crc(ChunkType),
46    /// Sequence number from an `fdAT` chunk - see
47    /// https://wiki.mozilla.org/APNG_Specification#.60fdAT.60:_The_Frame_Data_Chunk
48    ApngSequenceNumber,
49}
50
51#[derive(Debug)]
52enum State {
53    /// In this state we are reading a u32 value from external input.  We start with
54    /// `accumulated_count` set to `0`. After reading or accumulating the required 4 bytes we will
55    /// call `parse_32` which will then move onto the next state.
56    U32 {
57        kind: U32ValueKind,
58        bytes: [u8; 4],
59        accumulated_count: usize,
60    },
61    /// In this state we are reading chunk data from external input, and appending it to
62    /// `ChunkState::raw_bytes`.
63    ReadChunkData(ChunkType),
64    /// In this state we check if all chunk data has been already read into `ChunkState::raw_bytes`
65    /// and if so then we parse the chunk.  Otherwise, we go back to the `ReadChunkData` state.
66    ParseChunkData(ChunkType),
67    /// In this state we are reading image data from external input and feeding it directly into
68    /// `StreamingDecoder::inflater`.
69    ImageData(ChunkType),
70}
71
72impl State {
73    fn new_u32(kind: U32ValueKind) -> Self {
74        Self::U32 {
75            kind,
76            bytes: [0; 4],
77            accumulated_count: 0,
78        }
79    }
80}
81
82#[derive(Debug)]
83/// Result of the decoding process
84pub enum Decoded {
85    /// Nothing decoded yet
86    Nothing,
87    Header(u32, u32, BitDepth, ColorType, bool),
88    ChunkBegin(u32, ChunkType),
89    ChunkComplete(u32, ChunkType),
90    PixelDimensions(PixelDimensions),
91    AnimationControl(AnimationControl),
92    FrameControl(FrameControl),
93    /// Decoded raw image data.
94    ImageData,
95    /// The last of a consecutive chunk of IDAT was done.
96    /// This is distinct from ChunkComplete which only marks that some IDAT chunk was completed but
97    /// not that no additional IDAT chunk follows.
98    ImageDataFlushed,
99    PartialChunk(ChunkType),
100    ImageEnd,
101}
102
103/// Any kind of error during PNG decoding.
104///
105/// This enumeration provides a very rough analysis on the origin of the failure. That is, each
106/// variant corresponds to one kind of actor causing the error. It should not be understood as a
107/// direct blame but can inform the search for a root cause or if such a search is required.
108#[derive(Debug)]
109pub enum DecodingError {
110    /// An error in IO of the underlying reader.
111    ///
112    /// Note that some IO errors may be recoverable - decoding may be retried after the
113    /// error is resolved.  For example, decoding from a slow stream of data (e.g. decoding from a
114    /// network stream) may occasionally result in [std::io::ErrorKind::UnexpectedEof] kind of
115    /// error, but decoding can resume when more data becomes available.
116    IoError(io::Error),
117    /// The input image was not a valid PNG.
118    ///
119    /// There isn't a lot that can be done here, except if the program itself was responsible for
120    /// creating this image then investigate the generator. This is internally implemented with a
121    /// large Enum. If You are interested in accessing some of the more exact information on the
122    /// variant then we can discuss in an issue.
123    Format(FormatError),
124    /// An interface was used incorrectly.
125    ///
126    /// This is used in cases where it's expected that the programmer might trip up and stability
127    /// could be affected. For example when:
128    ///
129    /// * The decoder is polled for more animation frames despite being done (or not being animated
130    ///   in the first place).
131    /// * The output buffer does not have the required size.
132    ///
133    /// As a rough guideline for introducing new variants parts of the requirements are dynamically
134    /// derived from the (untrusted) input data while the other half is from the caller. In the
135    /// above cases the number of frames respectively the size is determined by the file while the
136    /// number of calls
137    ///
138    /// If you're an application you might want to signal that a bug report is appreciated.
139    Parameter(ParameterError),
140    /// The image would have required exceeding the limits configured with the decoder.
141    ///
142    /// Note that Your allocations, e.g. when reading into a pre-allocated buffer, is __NOT__
143    /// considered part of the limits. Nevertheless, required intermediate buffers such as for
144    /// singular lines is checked against the limit.
145    ///
146    /// Note that this is a best-effort basis.
147    LimitsExceeded,
148}
149
150#[derive(Debug)]
151pub struct FormatError {
152    inner: FormatErrorInner,
153}
154
155#[derive(Debug)]
156pub(crate) enum FormatErrorInner {
157    /// Bad framing.
158    CrcMismatch {
159        /// Stored CRC32 value
160        crc_val: u32,
161        /// Calculated CRC32 sum
162        crc_sum: u32,
163        /// The chunk type that has the CRC mismatch.
164        chunk: ChunkType,
165    },
166    /// Not a PNG, the magic signature is missing.
167    InvalidSignature,
168    // Errors of chunk level ordering, missing etc.
169    /// Ihdr must occur.
170    MissingIhdr,
171    /// Fctl must occur if an animated chunk occurs.
172    MissingFctl,
173    /// Image data that was indicated in IHDR or acTL is missing.
174    MissingImageData,
175    /// 4.3., Must be first.
176    ChunkBeforeIhdr {
177        kind: ChunkType,
178    },
179    /// 4.3., some chunks must be before IDAT.
180    AfterIdat {
181        kind: ChunkType,
182    },
183    /// 4.3., some chunks must be before PLTE.
184    AfterPlte {
185        kind: ChunkType,
186    },
187    /// 4.3., some chunks must be between PLTE and IDAT.
188    OutsidePlteIdat {
189        kind: ChunkType,
190    },
191    /// 4.3., some chunks must be unique.
192    DuplicateChunk {
193        kind: ChunkType,
194    },
195    /// Specifically for fdat there is an embedded sequence number for chunks.
196    ApngOrder {
197        /// The sequence number in the chunk.
198        present: u32,
199        /// The one that should have been present.
200        expected: u32,
201    },
202    // Errors specific to particular chunk data to be validated.
203    /// The palette did not even contain a single pixel data.
204    ShortPalette {
205        expected: usize,
206        len: usize,
207    },
208    /// A palletized image did not have a palette.
209    PaletteRequired,
210    /// The color-depth combination is not valid according to Table 11.1.
211    InvalidColorBitDepth {
212        color_type: ColorType,
213        bit_depth: BitDepth,
214    },
215    ColorWithBadTrns(ColorType),
216    /// The image width or height is zero.
217    InvalidDimensions,
218    InvalidBitDepth(u8),
219    InvalidColorType(u8),
220    InvalidDisposeOp(u8),
221    InvalidBlendOp(u8),
222    InvalidUnit(u8),
223    /// The rendering intent of the sRGB chunk is invalid.
224    InvalidSrgbRenderingIntent(u8),
225    UnknownCompressionMethod(u8),
226    UnknownFilterMethod(u8),
227    UnknownInterlaceMethod(u8),
228    /// The subframe is not in bounds of the image.
229    /// TODO: fields with relevant data.
230    BadSubFrameBounds {},
231    // Errors specific to the IDAT/fdAT chunks.
232    /// The compression of the data stream was faulty.
233    CorruptFlateStream {
234        err: fdeflate::DecompressionError,
235    },
236    /// The image data chunk was too short for the expected pixel count.
237    NoMoreImageData,
238    /// Bad text encoding
239    BadTextEncoding(TextDecodingError),
240    /// fdAT shorter than 4 bytes
241    FdatShorterThanFourBytes,
242    /// "11.2.4 IDAT Image data" section of the PNG spec says: There may be multiple IDAT chunks;
243    /// if so, they shall appear consecutively with no other intervening chunks.
244    /// `UnexpectedRestartOfDataChunkSequence{kind: IDAT}` indicates that there were "intervening
245    /// chunks".
246    ///
247    /// The APNG spec doesn't directly describe an error similar to `CantInterleaveIdatChunks`,
248    /// but we require that a new sequence of consecutive `fdAT` chunks cannot appear unless we've
249    /// seen an `fcTL` chunk.
250    UnexpectedRestartOfDataChunkSequence {
251        kind: ChunkType,
252    },
253    /// Failure to parse a chunk, because the chunk didn't contain enough bytes.
254    ChunkTooShort {
255        kind: ChunkType,
256    },
257}
258
259impl error::Error for DecodingError {
260    fn cause(&self) -> Option<&(dyn error::Error + 'static)> {
261        match self {
262            DecodingError::IoError(err) => Some(err),
263            _ => None,
264        }
265    }
266}
267
268impl fmt::Display for DecodingError {
269    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
270        use self::DecodingError::*;
271        match self {
272            IoError(err) => write!(fmt, "{}", err),
273            Parameter(desc) => write!(fmt, "{}", &desc),
274            Format(desc) => write!(fmt, "{}", desc),
275            LimitsExceeded => write!(fmt, "limits are exceeded"),
276        }
277    }
278}
279
280impl fmt::Display for FormatError {
281    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
282        use FormatErrorInner::*;
283        match &self.inner {
284            CrcMismatch {
285                crc_val,
286                crc_sum,
287                chunk,
288                ..
289            } => write!(
290                fmt,
291                "CRC error: expected 0x{:x} have 0x{:x} while decoding {:?} chunk.",
292                crc_val, crc_sum, chunk
293            ),
294            MissingIhdr => write!(fmt, "IHDR chunk missing"),
295            MissingFctl => write!(fmt, "fcTL chunk missing before fdAT chunk."),
296            MissingImageData => write!(fmt, "IDAT or fdAT chunk is missing."),
297            ChunkBeforeIhdr { kind } => write!(fmt, "{:?} chunk appeared before IHDR chunk", kind),
298            AfterIdat { kind } => write!(fmt, "Chunk {:?} is invalid after IDAT chunk.", kind),
299            AfterPlte { kind } => write!(fmt, "Chunk {:?} is invalid after PLTE chunk.", kind),
300            OutsidePlteIdat { kind } => write!(
301                fmt,
302                "Chunk {:?} must appear between PLTE and IDAT chunks.",
303                kind
304            ),
305            DuplicateChunk { kind } => write!(fmt, "Chunk {:?} must appear at most once.", kind),
306            ApngOrder { present, expected } => write!(
307                fmt,
308                "Sequence is not in order, expected #{} got #{}.",
309                expected, present,
310            ),
311            ShortPalette { expected, len } => write!(
312                fmt,
313                "Not enough palette entries, expect {} got {}.",
314                expected, len
315            ),
316            PaletteRequired => write!(fmt, "Missing palette of indexed image."),
317            InvalidDimensions => write!(fmt, "Invalid image dimensions"),
318            InvalidColorBitDepth {
319                color_type,
320                bit_depth,
321            } => write!(
322                fmt,
323                "Invalid color/depth combination in header: {:?}/{:?}",
324                color_type, bit_depth,
325            ),
326            ColorWithBadTrns(color_type) => write!(
327                fmt,
328                "Transparency chunk found for color type {:?}.",
329                color_type
330            ),
331            InvalidBitDepth(nr) => write!(fmt, "Invalid bit depth {}.", nr),
332            InvalidColorType(nr) => write!(fmt, "Invalid color type {}.", nr),
333            InvalidDisposeOp(nr) => write!(fmt, "Invalid dispose op {}.", nr),
334            InvalidBlendOp(nr) => write!(fmt, "Invalid blend op {}.", nr),
335            InvalidUnit(nr) => write!(fmt, "Invalid physical pixel size unit {}.", nr),
336            InvalidSrgbRenderingIntent(nr) => write!(fmt, "Invalid sRGB rendering intent {}.", nr),
337            UnknownCompressionMethod(nr) => write!(fmt, "Unknown compression method {}.", nr),
338            UnknownFilterMethod(nr) => write!(fmt, "Unknown filter method {}.", nr),
339            UnknownInterlaceMethod(nr) => write!(fmt, "Unknown interlace method {}.", nr),
340            BadSubFrameBounds {} => write!(fmt, "Sub frame is out-of-bounds."),
341            InvalidSignature => write!(fmt, "Invalid PNG signature."),
342            NoMoreImageData => write!(
343                fmt,
344                "IDAT or fDAT chunk does not have enough data for image."
345            ),
346            CorruptFlateStream { err } => {
347                write!(fmt, "Corrupt deflate stream. ")?;
348                write!(fmt, "{:?}", err)
349            }
350            // TODO: Wrap more info in the enum variant
351            BadTextEncoding(tde) => {
352                match tde {
353                    TextDecodingError::Unrepresentable => {
354                        write!(fmt, "Unrepresentable data in tEXt chunk.")
355                    }
356                    TextDecodingError::InvalidKeywordSize => {
357                        write!(fmt, "Keyword empty or longer than 79 bytes.")
358                    }
359                    TextDecodingError::MissingNullSeparator => {
360                        write!(fmt, "No null separator in tEXt chunk.")
361                    }
362                    TextDecodingError::InflationError => {
363                        write!(fmt, "Invalid compressed text data.")
364                    }
365                    TextDecodingError::OutOfDecompressionSpace => {
366                        write!(fmt, "Out of decompression space. Try with a larger limit.")
367                    }
368                    TextDecodingError::InvalidCompressionMethod => {
369                        write!(fmt, "Using an unrecognized byte as compression method.")
370                    }
371                    TextDecodingError::InvalidCompressionFlag => {
372                        write!(fmt, "Using a flag that is not 0 or 255 as a compression flag for iTXt chunk.")
373                    }
374                    TextDecodingError::MissingCompressionFlag => {
375                        write!(fmt, "No compression flag in the iTXt chunk.")
376                    }
377                }
378            }
379            FdatShorterThanFourBytes => write!(fmt, "fdAT chunk shorter than 4 bytes"),
380            UnexpectedRestartOfDataChunkSequence { kind } => {
381                write!(fmt, "Unexpected restart of {:?} chunk sequence", kind)
382            }
383            ChunkTooShort { kind } => {
384                write!(fmt, "Chunk is too short: {:?}", kind)
385            }
386        }
387    }
388}
389
390impl From<io::Error> for DecodingError {
391    fn from(err: io::Error) -> DecodingError {
392        DecodingError::IoError(err)
393    }
394}
395
396impl From<FormatError> for DecodingError {
397    fn from(err: FormatError) -> DecodingError {
398        DecodingError::Format(err)
399    }
400}
401
402impl From<FormatErrorInner> for FormatError {
403    fn from(inner: FormatErrorInner) -> Self {
404        FormatError { inner }
405    }
406}
407
408impl From<DecodingError> for io::Error {
409    fn from(err: DecodingError) -> io::Error {
410        match err {
411            DecodingError::IoError(err) => err,
412            err => io::Error::new(io::ErrorKind::Other, err.to_string()),
413        }
414    }
415}
416
417impl From<TextDecodingError> for DecodingError {
418    fn from(tbe: TextDecodingError) -> Self {
419        DecodingError::Format(FormatError {
420            inner: FormatErrorInner::BadTextEncoding(tbe),
421        })
422    }
423}
424
425/// Decoder configuration options
426#[derive(Clone)]
427pub struct DecodeOptions {
428    ignore_adler32: bool,
429    ignore_crc: bool,
430    ignore_text_chunk: bool,
431    ignore_iccp_chunk: bool,
432    skip_ancillary_crc_failures: bool,
433}
434
435impl Default for DecodeOptions {
436    fn default() -> Self {
437        Self {
438            ignore_adler32: true,
439            ignore_crc: false,
440            ignore_text_chunk: false,
441            ignore_iccp_chunk: false,
442            skip_ancillary_crc_failures: true,
443        }
444    }
445}
446
447impl DecodeOptions {
448    /// When set, the decoder will not compute and verify the Adler-32 checksum.
449    ///
450    /// Defaults to `true`.
451    pub fn set_ignore_adler32(&mut self, ignore_adler32: bool) {
452        self.ignore_adler32 = ignore_adler32;
453    }
454
455    /// When set, the decoder will not compute and verify the CRC code.
456    ///
457    /// Defaults to `false`.
458    pub fn set_ignore_crc(&mut self, ignore_crc: bool) {
459        self.ignore_crc = ignore_crc;
460    }
461
462    /// Flag to ignore computing and verifying the Adler-32 checksum and CRC
463    /// code.
464    pub fn set_ignore_checksums(&mut self, ignore_checksums: bool) {
465        self.ignore_adler32 = ignore_checksums;
466        self.ignore_crc = ignore_checksums;
467    }
468
469    /// Ignore text chunks while decoding.
470    ///
471    /// Defaults to `false`.
472    pub fn set_ignore_text_chunk(&mut self, ignore_text_chunk: bool) {
473        self.ignore_text_chunk = ignore_text_chunk;
474    }
475
476    /// Ignore ICCP chunks while decoding.
477    ///
478    /// Defaults to `false`.
479    pub fn set_ignore_iccp_chunk(&mut self, ignore_iccp_chunk: bool) {
480        self.ignore_iccp_chunk = ignore_iccp_chunk;
481    }
482
483    /// Ignore ancillary chunks if CRC fails
484    ///
485    /// Defaults to `true`
486    pub fn set_skip_ancillary_crc_failures(&mut self, skip_ancillary_crc_failures: bool) {
487        self.skip_ancillary_crc_failures = skip_ancillary_crc_failures;
488    }
489}
490
491/// PNG StreamingDecoder (low-level interface)
492///
493/// By default, the decoder does not verify Adler-32 checksum computation. To
494/// enable checksum verification, set it with [`StreamingDecoder::set_ignore_adler32`]
495/// before starting decompression.
496pub struct StreamingDecoder {
497    state: Option<State>,
498    current_chunk: ChunkState,
499    /// The inflater state handling consecutive `IDAT` and `fdAT` chunks.
500    inflater: ZlibStream,
501    /// The complete image info read from all prior chunks.
502    pub(crate) info: Option<Info<'static>>,
503    /// The animation chunk sequence number.
504    current_seq_no: Option<u32>,
505    /// Whether we have already seen a start of an IDAT chunk.  (Used to validate chunk ordering -
506    /// some chunk types can only appear before or after an IDAT chunk.)
507    have_idat: bool,
508    /// Whether we are ready for a start of an `IDAT` chunk sequence.  Initially `true` and set to
509    /// `false` when the first sequence of consecutive `IDAT` chunks ends.
510    ready_for_idat_chunks: bool,
511    /// Whether we are ready for a start of an `fdAT` chunk sequence.  Initially `false`.  Set to
512    /// `true` after encountering an `fcTL` chunk. Set to `false` when a sequence of consecutive
513    /// `fdAT` chunks ends.
514    ready_for_fdat_chunks: bool,
515    /// Whether we have already seen an iCCP chunk. Used to prevent parsing of duplicate iCCP chunks.
516    have_iccp: bool,
517    decode_options: DecodeOptions,
518    pub(crate) limits: Limits,
519}
520
521struct ChunkState {
522    /// The type of the current chunk.
523    /// Relevant for `IDAT` and `fdAT` which aggregate consecutive chunks of their own type.
524    type_: ChunkType,
525
526    /// Partial crc until now.
527    crc: Crc32,
528
529    /// Remaining bytes to be read.
530    remaining: u32,
531
532    /// Non-decoded bytes in the chunk.
533    raw_bytes: Vec<u8>,
534}
535
536impl StreamingDecoder {
537    /// Creates a new StreamingDecoder
538    ///
539    /// Allocates the internal buffers.
540    pub fn new() -> StreamingDecoder {
541        StreamingDecoder::new_with_options(DecodeOptions::default())
542    }
543
544    pub fn new_with_options(decode_options: DecodeOptions) -> StreamingDecoder {
545        let mut inflater = ZlibStream::new();
546        inflater.set_ignore_adler32(decode_options.ignore_adler32);
547
548        StreamingDecoder {
549            state: Some(State::new_u32(U32ValueKind::Signature1stU32)),
550            current_chunk: ChunkState::default(),
551            inflater,
552            info: None,
553            current_seq_no: None,
554            have_idat: false,
555            have_iccp: false,
556            ready_for_idat_chunks: true,
557            ready_for_fdat_chunks: false,
558            decode_options,
559            limits: Limits { bytes: usize::MAX },
560        }
561    }
562
563    /// Resets the StreamingDecoder
564    pub fn reset(&mut self) {
565        self.state = Some(State::new_u32(U32ValueKind::Signature1stU32));
566        self.current_chunk.crc = Crc32::new();
567        self.current_chunk.remaining = 0;
568        self.current_chunk.raw_bytes.clear();
569        self.inflater.reset();
570        self.info = None;
571        self.current_seq_no = None;
572        self.have_idat = false;
573    }
574
575    /// Provides access to the inner `info` field
576    pub fn info(&self) -> Option<&Info<'static>> {
577        self.info.as_ref()
578    }
579
580    pub fn set_ignore_text_chunk(&mut self, ignore_text_chunk: bool) {
581        self.decode_options.set_ignore_text_chunk(ignore_text_chunk);
582    }
583
584    pub fn set_ignore_iccp_chunk(&mut self, ignore_iccp_chunk: bool) {
585        self.decode_options.set_ignore_iccp_chunk(ignore_iccp_chunk);
586    }
587
588    /// Return whether the decoder is set to ignore the Adler-32 checksum.
589    pub fn ignore_adler32(&self) -> bool {
590        self.inflater.ignore_adler32()
591    }
592
593    /// Set whether to compute and verify the Adler-32 checksum during
594    /// decompression. Return `true` if the flag was successfully set.
595    ///
596    /// The decoder defaults to `true`.
597    ///
598    /// This flag cannot be modified after decompression has started until the
599    /// [`StreamingDecoder`] is reset.
600    pub fn set_ignore_adler32(&mut self, ignore_adler32: bool) -> bool {
601        self.inflater.set_ignore_adler32(ignore_adler32)
602    }
603
604    /// Set whether to compute and verify the Adler-32 checksum during
605    /// decompression.
606    ///
607    /// The decoder defaults to `false`.
608    pub fn set_ignore_crc(&mut self, ignore_crc: bool) {
609        self.decode_options.set_ignore_crc(ignore_crc)
610    }
611
612    /// Ignore ancillary chunks if CRC fails
613    ///
614    /// Defaults to `true`
615    pub fn set_skip_ancillary_crc_failures(&mut self, skip_ancillary_crc_failures: bool) {
616        self.decode_options
617            .set_skip_ancillary_crc_failures(skip_ancillary_crc_failures)
618    }
619
620    /// Low level StreamingDecoder interface.
621    ///
622    /// Allows to stream partial data to the encoder. Returns a tuple containing the bytes that have
623    /// been consumed from the input buffer and the current decoding result. If the decoded chunk
624    /// was an image data chunk, it also appends the read data to `image_data`.
625    pub fn update(
626        &mut self,
627        mut buf: &[u8],
628        image_data: &mut Vec<u8>,
629    ) -> Result<(usize, Decoded), DecodingError> {
630        let len = buf.len();
631        while !buf.is_empty() && self.state.is_some() {
632            match self.next_state(buf, image_data) {
633                Ok((bytes, Decoded::Nothing)) => buf = &buf[bytes..],
634                Ok((bytes, result)) => {
635                    buf = &buf[bytes..];
636                    return Ok((len - buf.len(), result));
637                }
638                Err(err) => return Err(err),
639            }
640        }
641        Ok((len - buf.len(), Decoded::Nothing))
642    }
643
644    fn next_state(
645        &mut self,
646        buf: &[u8],
647        image_data: &mut Vec<u8>,
648    ) -> Result<(usize, Decoded), DecodingError> {
649        use self::State::*;
650
651        // Driver should ensure that state is never None
652        let state = self.state.take().unwrap();
653
654        match state {
655            U32 {
656                kind,
657                mut bytes,
658                mut accumulated_count,
659            } => {
660                debug_assert!(accumulated_count <= 4);
661                if accumulated_count == 0 && buf.len() >= 4 {
662                    // Handling these `accumulated_count` and `buf.len()` values in a separate `if`
663                    // branch is not strictly necessary - the `else` statement below is already
664                    // capable of handling these values.  The main reason for special-casing these
665                    // values is that they occur fairly frequently and special-casing them results
666                    // in performance gains.
667                    const CONSUMED_BYTES: usize = 4;
668                    self.parse_u32(kind, &buf[0..4], image_data)
669                        .map(|decoded| (CONSUMED_BYTES, decoded))
670                } else {
671                    let remaining_count = 4 - accumulated_count;
672                    let consumed_bytes = {
673                        let available_count = min(remaining_count, buf.len());
674                        bytes[accumulated_count..accumulated_count + available_count]
675                            .copy_from_slice(&buf[0..available_count]);
676                        accumulated_count += available_count;
677                        available_count
678                    };
679
680                    if accumulated_count < 4 {
681                        self.state = Some(U32 {
682                            kind,
683                            bytes,
684                            accumulated_count,
685                        });
686                        Ok((consumed_bytes, Decoded::Nothing))
687                    } else {
688                        debug_assert_eq!(accumulated_count, 4);
689                        self.parse_u32(kind, &bytes, image_data)
690                            .map(|decoded| (consumed_bytes, decoded))
691                    }
692                }
693            }
694            ParseChunkData(type_str) => {
695                debug_assert!(type_str != IDAT && type_str != chunk::fdAT);
696                if self.current_chunk.remaining == 0 {
697                    // Got complete chunk.
698                    Ok((0, self.parse_chunk(type_str)?))
699                } else {
700                    // Make sure we have room to read more of the chunk.
701                    // We need it fully before parsing.
702                    self.reserve_current_chunk()?;
703
704                    self.state = Some(ReadChunkData(type_str));
705                    Ok((0, Decoded::PartialChunk(type_str)))
706                }
707            }
708            ReadChunkData(type_str) => {
709                debug_assert!(type_str != IDAT && type_str != chunk::fdAT);
710                if self.current_chunk.remaining == 0 {
711                    self.state = Some(State::new_u32(U32ValueKind::Crc(type_str)));
712                    Ok((0, Decoded::Nothing))
713                } else {
714                    let ChunkState {
715                        crc,
716                        remaining,
717                        raw_bytes,
718                        type_: _,
719                    } = &mut self.current_chunk;
720
721                    let buf_avail = raw_bytes.capacity() - raw_bytes.len();
722                    let bytes_avail = min(buf.len(), buf_avail);
723                    let n = min(*remaining, bytes_avail as u32);
724                    if buf_avail == 0 {
725                        self.state = Some(ParseChunkData(type_str));
726                        Ok((0, Decoded::Nothing))
727                    } else {
728                        let buf = &buf[..n as usize];
729                        if !self.decode_options.ignore_crc {
730                            crc.update(buf);
731                        }
732                        raw_bytes.extend_from_slice(buf);
733
734                        *remaining -= n;
735                        if *remaining == 0 {
736                            self.state = Some(ParseChunkData(type_str));
737                        } else {
738                            self.state = Some(ReadChunkData(type_str));
739                        }
740                        Ok((n as usize, Decoded::Nothing))
741                    }
742                }
743            }
744            ImageData(type_str) => {
745                debug_assert!(type_str == IDAT || type_str == chunk::fdAT);
746                let len = std::cmp::min(buf.len(), self.current_chunk.remaining as usize);
747                let buf = &buf[..len];
748                let consumed = self.inflater.decompress(buf, image_data)?;
749                self.current_chunk.crc.update(&buf[..consumed]);
750                self.current_chunk.remaining -= consumed as u32;
751                if self.current_chunk.remaining == 0 {
752                    self.state = Some(State::new_u32(U32ValueKind::Crc(type_str)));
753                } else {
754                    self.state = Some(ImageData(type_str));
755                }
756                Ok((consumed, Decoded::ImageData))
757            }
758        }
759    }
760
761    fn parse_u32(
762        &mut self,
763        kind: U32ValueKind,
764        u32_be_bytes: &[u8],
765        image_data: &mut Vec<u8>,
766    ) -> Result<Decoded, DecodingError> {
767        debug_assert_eq!(u32_be_bytes.len(), 4);
768        let bytes = u32_be_bytes.try_into().unwrap();
769        let val = u32::from_be_bytes(bytes);
770
771        match kind {
772            U32ValueKind::Signature1stU32 => {
773                if bytes == [137, 80, 78, 71] {
774                    self.state = Some(State::new_u32(U32ValueKind::Signature2ndU32));
775                    Ok(Decoded::Nothing)
776                } else {
777                    Err(DecodingError::Format(
778                        FormatErrorInner::InvalidSignature.into(),
779                    ))
780                }
781            }
782            U32ValueKind::Signature2ndU32 => {
783                if bytes == [13, 10, 26, 10] {
784                    self.state = Some(State::new_u32(U32ValueKind::Length));
785                    Ok(Decoded::Nothing)
786                } else {
787                    Err(DecodingError::Format(
788                        FormatErrorInner::InvalidSignature.into(),
789                    ))
790                }
791            }
792            U32ValueKind::Length => {
793                self.state = Some(State::new_u32(U32ValueKind::Type { length: val }));
794                Ok(Decoded::Nothing)
795            }
796            U32ValueKind::Type { length } => {
797                let type_str = ChunkType(bytes);
798                if self.info.is_none() && type_str != IHDR {
799                    return Err(DecodingError::Format(
800                        FormatErrorInner::ChunkBeforeIhdr { kind: type_str }.into(),
801                    ));
802                }
803                if type_str != self.current_chunk.type_
804                    && (self.current_chunk.type_ == IDAT || self.current_chunk.type_ == chunk::fdAT)
805                {
806                    self.current_chunk.type_ = type_str;
807                    self.inflater.finish_compressed_chunks(image_data)?;
808                    self.inflater.reset();
809                    self.ready_for_idat_chunks = false;
810                    self.ready_for_fdat_chunks = false;
811                    self.state = Some(State::U32 {
812                        kind,
813                        bytes,
814                        accumulated_count: 4,
815                    });
816                    return Ok(Decoded::ImageDataFlushed);
817                }
818                self.state = match type_str {
819                    chunk::fdAT => {
820                        if !self.ready_for_fdat_chunks {
821                            return Err(DecodingError::Format(
822                                FormatErrorInner::UnexpectedRestartOfDataChunkSequence {
823                                    kind: chunk::fdAT,
824                                }
825                                .into(),
826                            ));
827                        }
828                        if length < 4 {
829                            return Err(DecodingError::Format(
830                                FormatErrorInner::FdatShorterThanFourBytes.into(),
831                            ));
832                        }
833                        Some(State::new_u32(U32ValueKind::ApngSequenceNumber))
834                    }
835                    IDAT => {
836                        if !self.ready_for_idat_chunks {
837                            return Err(DecodingError::Format(
838                                FormatErrorInner::UnexpectedRestartOfDataChunkSequence {
839                                    kind: IDAT,
840                                }
841                                .into(),
842                            ));
843                        }
844                        self.have_idat = true;
845                        Some(State::ImageData(type_str))
846                    }
847                    _ => Some(State::ReadChunkData(type_str)),
848                };
849                self.current_chunk.type_ = type_str;
850                if !self.decode_options.ignore_crc {
851                    self.current_chunk.crc.reset();
852                    self.current_chunk.crc.update(&type_str.0);
853                }
854                self.current_chunk.remaining = length;
855                self.current_chunk.raw_bytes.clear();
856                Ok(Decoded::ChunkBegin(length, type_str))
857            }
858            U32ValueKind::Crc(type_str) => {
859                // If ignore_crc is set, do not calculate CRC. We set
860                // sum=val so that it short-circuits to true in the next
861                // if-statement block
862                let sum = if self.decode_options.ignore_crc {
863                    val
864                } else {
865                    self.current_chunk.crc.clone().finalize()
866                };
867
868                if val == sum || CHECKSUM_DISABLED {
869                    self.state = Some(State::new_u32(U32ValueKind::Length));
870                    if type_str == IEND {
871                        Ok(Decoded::ImageEnd)
872                    } else {
873                        Ok(Decoded::ChunkComplete(val, type_str))
874                    }
875                } else if self.decode_options.skip_ancillary_crc_failures
876                    && !chunk::is_critical(type_str)
877                {
878                    // Ignore ancillary chunk with invalid CRC
879                    self.state = Some(State::new_u32(U32ValueKind::Length));
880                    Ok(Decoded::Nothing)
881                } else {
882                    Err(DecodingError::Format(
883                        FormatErrorInner::CrcMismatch {
884                            crc_val: val,
885                            crc_sum: sum,
886                            chunk: type_str,
887                        }
888                        .into(),
889                    ))
890                }
891            }
892            U32ValueKind::ApngSequenceNumber => {
893                debug_assert_eq!(self.current_chunk.type_, chunk::fdAT);
894                let next_seq_no = val;
895
896                // Should be verified by the FdatShorterThanFourBytes check earlier.
897                debug_assert!(self.current_chunk.remaining >= 4);
898                self.current_chunk.remaining -= 4;
899
900                if let Some(seq_no) = self.current_seq_no {
901                    if next_seq_no != seq_no + 1 {
902                        return Err(DecodingError::Format(
903                            FormatErrorInner::ApngOrder {
904                                present: next_seq_no,
905                                expected: seq_no + 1,
906                            }
907                            .into(),
908                        ));
909                    }
910                    self.current_seq_no = Some(next_seq_no);
911                } else {
912                    return Err(DecodingError::Format(FormatErrorInner::MissingFctl.into()));
913                }
914
915                if !self.decode_options.ignore_crc {
916                    let data = next_seq_no.to_be_bytes();
917                    self.current_chunk.crc.update(&data);
918                }
919
920                self.state = Some(State::ImageData(chunk::fdAT));
921                Ok(Decoded::PartialChunk(chunk::fdAT))
922            }
923        }
924    }
925
926    fn reserve_current_chunk(&mut self) -> Result<(), DecodingError> {
927        let max = self.limits.bytes;
928        let buffer = &mut self.current_chunk.raw_bytes;
929
930        // Double if necessary, but no more than until the limit is reached.
931        let reserve_size = max.saturating_sub(buffer.capacity()).min(buffer.len());
932        self.limits.reserve_bytes(reserve_size)?;
933        buffer.reserve_exact(reserve_size);
934
935        if buffer.capacity() == buffer.len() {
936            Err(DecodingError::LimitsExceeded)
937        } else {
938            Ok(())
939        }
940    }
941
942    fn parse_chunk(&mut self, type_str: ChunkType) -> Result<Decoded, DecodingError> {
943        self.state = Some(State::new_u32(U32ValueKind::Crc(type_str)));
944        let parse_result = match type_str {
945            IHDR => self.parse_ihdr(),
946            chunk::PLTE => self.parse_plte(),
947            chunk::tRNS => self.parse_trns(),
948            chunk::pHYs => self.parse_phys(),
949            chunk::gAMA => self.parse_gama(),
950            chunk::acTL => self.parse_actl(),
951            chunk::fcTL => self.parse_fctl(),
952            chunk::cHRM => self.parse_chrm(),
953            chunk::sRGB => self.parse_srgb(),
954            chunk::iCCP if !self.decode_options.ignore_iccp_chunk => self.parse_iccp(),
955            chunk::tEXt if !self.decode_options.ignore_text_chunk => self.parse_text(),
956            chunk::zTXt if !self.decode_options.ignore_text_chunk => self.parse_ztxt(),
957            chunk::iTXt if !self.decode_options.ignore_text_chunk => self.parse_itxt(),
958            _ => Ok(Decoded::PartialChunk(type_str)),
959        };
960
961        let parse_result = parse_result.map_err(|e| {
962            self.state = None;
963            match e {
964                // `parse_chunk` is invoked after gathering **all** bytes of a chunk, so
965                // `UnexpectedEof` from something like `read_be` is permanent and indicates an
966                // invalid PNG that should be represented as a `FormatError`, rather than as a
967                // (potentially recoverable) `IoError` / `UnexpectedEof`.
968                DecodingError::IoError(e) if e.kind() == std::io::ErrorKind::UnexpectedEof => {
969                    let fmt_err: FormatError =
970                        FormatErrorInner::ChunkTooShort { kind: type_str }.into();
971                    fmt_err.into()
972                }
973                e => e,
974            }
975        });
976
977        parse_result
978    }
979
980    fn parse_fctl(&mut self) -> Result<Decoded, DecodingError> {
981        let mut buf = &self.current_chunk.raw_bytes[..];
982        let next_seq_no = buf.read_be()?;
983
984        // Assuming that fcTL is required before *every* fdAT-sequence
985        self.current_seq_no = Some(if let Some(seq_no) = self.current_seq_no {
986            if next_seq_no != seq_no + 1 {
987                return Err(DecodingError::Format(
988                    FormatErrorInner::ApngOrder {
989                        expected: seq_no + 1,
990                        present: next_seq_no,
991                    }
992                    .into(),
993                ));
994            }
995            next_seq_no
996        } else {
997            if next_seq_no != 0 {
998                return Err(DecodingError::Format(
999                    FormatErrorInner::ApngOrder {
1000                        expected: 0,
1001                        present: next_seq_no,
1002                    }
1003                    .into(),
1004                ));
1005            }
1006            0
1007        });
1008        self.inflater.reset();
1009        self.ready_for_fdat_chunks = true;
1010        let fc = FrameControl {
1011            sequence_number: next_seq_no,
1012            width: buf.read_be()?,
1013            height: buf.read_be()?,
1014            x_offset: buf.read_be()?,
1015            y_offset: buf.read_be()?,
1016            delay_num: buf.read_be()?,
1017            delay_den: buf.read_be()?,
1018            dispose_op: {
1019                let dispose_op = buf.read_be()?;
1020                match DisposeOp::from_u8(dispose_op) {
1021                    Some(dispose_op) => dispose_op,
1022                    None => {
1023                        return Err(DecodingError::Format(
1024                            FormatErrorInner::InvalidDisposeOp(dispose_op).into(),
1025                        ))
1026                    }
1027                }
1028            },
1029            blend_op: {
1030                let blend_op = buf.read_be()?;
1031                match BlendOp::from_u8(blend_op) {
1032                    Some(blend_op) => blend_op,
1033                    None => {
1034                        return Err(DecodingError::Format(
1035                            FormatErrorInner::InvalidBlendOp(blend_op).into(),
1036                        ))
1037                    }
1038                }
1039            },
1040        };
1041        self.info.as_ref().unwrap().validate(&fc)?;
1042        self.info.as_mut().unwrap().frame_control = Some(fc);
1043        Ok(Decoded::FrameControl(fc))
1044    }
1045
1046    fn parse_actl(&mut self) -> Result<Decoded, DecodingError> {
1047        if self.have_idat {
1048            Err(DecodingError::Format(
1049                FormatErrorInner::AfterIdat { kind: chunk::acTL }.into(),
1050            ))
1051        } else {
1052            let mut buf = &self.current_chunk.raw_bytes[..];
1053            let actl = AnimationControl {
1054                num_frames: buf.read_be()?,
1055                num_plays: buf.read_be()?,
1056            };
1057            self.info.as_mut().unwrap().animation_control = Some(actl);
1058            Ok(Decoded::AnimationControl(actl))
1059        }
1060    }
1061
1062    fn parse_plte(&mut self) -> Result<Decoded, DecodingError> {
1063        let info = self.info.as_mut().unwrap();
1064        if info.palette.is_some() {
1065            // Only one palette is allowed
1066            Err(DecodingError::Format(
1067                FormatErrorInner::DuplicateChunk { kind: chunk::PLTE }.into(),
1068            ))
1069        } else {
1070            self.limits
1071                .reserve_bytes(self.current_chunk.raw_bytes.len())?;
1072            info.palette = Some(Cow::Owned(self.current_chunk.raw_bytes.clone()));
1073            Ok(Decoded::Nothing)
1074        }
1075    }
1076
1077    fn parse_trns(&mut self) -> Result<Decoded, DecodingError> {
1078        let info = self.info.as_mut().unwrap();
1079        if info.trns.is_some() {
1080            return Err(DecodingError::Format(
1081                FormatErrorInner::DuplicateChunk { kind: chunk::PLTE }.into(),
1082            ));
1083        }
1084        let (color_type, bit_depth) = { (info.color_type, info.bit_depth as u8) };
1085        self.limits
1086            .reserve_bytes(self.current_chunk.raw_bytes.len())?;
1087        let mut vec = self.current_chunk.raw_bytes.clone();
1088        let len = vec.len();
1089        match color_type {
1090            ColorType::Grayscale => {
1091                if len < 2 {
1092                    return Err(DecodingError::Format(
1093                        FormatErrorInner::ShortPalette { expected: 2, len }.into(),
1094                    ));
1095                }
1096                if bit_depth < 16 {
1097                    vec[0] = vec[1];
1098                    vec.truncate(1);
1099                }
1100                info.trns = Some(Cow::Owned(vec));
1101                Ok(Decoded::Nothing)
1102            }
1103            ColorType::Rgb => {
1104                if len < 6 {
1105                    return Err(DecodingError::Format(
1106                        FormatErrorInner::ShortPalette { expected: 6, len }.into(),
1107                    ));
1108                }
1109                if bit_depth < 16 {
1110                    vec[0] = vec[1];
1111                    vec[1] = vec[3];
1112                    vec[2] = vec[5];
1113                    vec.truncate(3);
1114                }
1115                info.trns = Some(Cow::Owned(vec));
1116                Ok(Decoded::Nothing)
1117            }
1118            ColorType::Indexed => {
1119                // The transparency chunk must be after the palette chunk and
1120                // before the data chunk.
1121                if info.palette.is_none() {
1122                    return Err(DecodingError::Format(
1123                        FormatErrorInner::AfterPlte { kind: chunk::tRNS }.into(),
1124                    ));
1125                } else if self.have_idat {
1126                    return Err(DecodingError::Format(
1127                        FormatErrorInner::OutsidePlteIdat { kind: chunk::tRNS }.into(),
1128                    ));
1129                }
1130
1131                info.trns = Some(Cow::Owned(vec));
1132                Ok(Decoded::Nothing)
1133            }
1134            c => Err(DecodingError::Format(
1135                FormatErrorInner::ColorWithBadTrns(c).into(),
1136            )),
1137        }
1138    }
1139
1140    fn parse_phys(&mut self) -> Result<Decoded, DecodingError> {
1141        let info = self.info.as_mut().unwrap();
1142        if self.have_idat {
1143            Err(DecodingError::Format(
1144                FormatErrorInner::AfterIdat { kind: chunk::pHYs }.into(),
1145            ))
1146        } else if info.pixel_dims.is_some() {
1147            Err(DecodingError::Format(
1148                FormatErrorInner::DuplicateChunk { kind: chunk::pHYs }.into(),
1149            ))
1150        } else {
1151            let mut buf = &self.current_chunk.raw_bytes[..];
1152            let xppu = buf.read_be()?;
1153            let yppu = buf.read_be()?;
1154            let unit = buf.read_be()?;
1155            let unit = match Unit::from_u8(unit) {
1156                Some(unit) => unit,
1157                None => {
1158                    return Err(DecodingError::Format(
1159                        FormatErrorInner::InvalidUnit(unit).into(),
1160                    ))
1161                }
1162            };
1163            let pixel_dims = PixelDimensions { xppu, yppu, unit };
1164            info.pixel_dims = Some(pixel_dims);
1165            Ok(Decoded::PixelDimensions(pixel_dims))
1166        }
1167    }
1168
1169    fn parse_chrm(&mut self) -> Result<Decoded, DecodingError> {
1170        let info = self.info.as_mut().unwrap();
1171        if self.have_idat {
1172            Err(DecodingError::Format(
1173                FormatErrorInner::AfterIdat { kind: chunk::cHRM }.into(),
1174            ))
1175        } else if info.chrm_chunk.is_some() {
1176            Err(DecodingError::Format(
1177                FormatErrorInner::DuplicateChunk { kind: chunk::cHRM }.into(),
1178            ))
1179        } else {
1180            let mut buf = &self.current_chunk.raw_bytes[..];
1181            let white_x: u32 = buf.read_be()?;
1182            let white_y: u32 = buf.read_be()?;
1183            let red_x: u32 = buf.read_be()?;
1184            let red_y: u32 = buf.read_be()?;
1185            let green_x: u32 = buf.read_be()?;
1186            let green_y: u32 = buf.read_be()?;
1187            let blue_x: u32 = buf.read_be()?;
1188            let blue_y: u32 = buf.read_be()?;
1189
1190            let source_chromaticities = SourceChromaticities {
1191                white: (
1192                    ScaledFloat::from_scaled(white_x),
1193                    ScaledFloat::from_scaled(white_y),
1194                ),
1195                red: (
1196                    ScaledFloat::from_scaled(red_x),
1197                    ScaledFloat::from_scaled(red_y),
1198                ),
1199                green: (
1200                    ScaledFloat::from_scaled(green_x),
1201                    ScaledFloat::from_scaled(green_y),
1202                ),
1203                blue: (
1204                    ScaledFloat::from_scaled(blue_x),
1205                    ScaledFloat::from_scaled(blue_y),
1206                ),
1207            };
1208
1209            info.chrm_chunk = Some(source_chromaticities);
1210            // Ignore chromaticities if sRGB profile is used.
1211            if info.srgb.is_none() {
1212                info.source_chromaticities = Some(source_chromaticities);
1213            }
1214
1215            Ok(Decoded::Nothing)
1216        }
1217    }
1218
1219    fn parse_gama(&mut self) -> Result<Decoded, DecodingError> {
1220        let info = self.info.as_mut().unwrap();
1221        if self.have_idat {
1222            Err(DecodingError::Format(
1223                FormatErrorInner::AfterIdat { kind: chunk::gAMA }.into(),
1224            ))
1225        } else if info.gama_chunk.is_some() {
1226            Err(DecodingError::Format(
1227                FormatErrorInner::DuplicateChunk { kind: chunk::gAMA }.into(),
1228            ))
1229        } else {
1230            let mut buf = &self.current_chunk.raw_bytes[..];
1231            let source_gamma: u32 = buf.read_be()?;
1232            let source_gamma = ScaledFloat::from_scaled(source_gamma);
1233
1234            info.gama_chunk = Some(source_gamma);
1235            // Ignore chromaticities if sRGB profile is used.
1236            if info.srgb.is_none() {
1237                info.source_gamma = Some(source_gamma);
1238            }
1239
1240            Ok(Decoded::Nothing)
1241        }
1242    }
1243
1244    fn parse_srgb(&mut self) -> Result<Decoded, DecodingError> {
1245        let info = self.info.as_mut().unwrap();
1246        if self.have_idat {
1247            Err(DecodingError::Format(
1248                FormatErrorInner::AfterIdat { kind: chunk::acTL }.into(),
1249            ))
1250        } else if info.srgb.is_some() {
1251            Err(DecodingError::Format(
1252                FormatErrorInner::DuplicateChunk { kind: chunk::sRGB }.into(),
1253            ))
1254        } else {
1255            let mut buf = &self.current_chunk.raw_bytes[..];
1256            let raw: u8 = buf.read_be()?; // BE is is nonsense for single bytes, but this way the size is checked.
1257            let rendering_intent = crate::SrgbRenderingIntent::from_raw(raw).ok_or_else(|| {
1258                FormatError::from(FormatErrorInner::InvalidSrgbRenderingIntent(raw))
1259            })?;
1260
1261            // Set srgb and override source gamma and chromaticities.
1262            info.srgb = Some(rendering_intent);
1263            info.source_gamma = Some(crate::srgb::substitute_gamma());
1264            info.source_chromaticities = Some(crate::srgb::substitute_chromaticities());
1265            Ok(Decoded::Nothing)
1266        }
1267    }
1268
1269    fn parse_iccp(&mut self) -> Result<Decoded, DecodingError> {
1270        if self.have_idat {
1271            Err(DecodingError::Format(
1272                FormatErrorInner::AfterIdat { kind: chunk::iCCP }.into(),
1273            ))
1274        } else if self.have_iccp {
1275            // We have already encountered an iCCP chunk before.
1276            //
1277            // Section "4.2.2.4. iCCP Embedded ICC profile" of the spec says:
1278            //   > A file should contain at most one embedded profile,
1279            //   > whether explicit like iCCP or implicit like sRGB.
1280            // but
1281            //   * This is a "should", not a "must"
1282            //   * The spec also says that "All ancillary chunks are optional, in the sense that
1283            //     [...] decoders can ignore them."
1284            //   * The reference implementation (libpng) ignores the subsequent iCCP chunks
1285            //     (treating them as a benign error).
1286            Ok(Decoded::Nothing)
1287        } else {
1288            self.have_iccp = true;
1289            let _ = self.parse_iccp_raw();
1290            Ok(Decoded::Nothing)
1291        }
1292    }
1293
1294    fn parse_iccp_raw(&mut self) -> Result<(), DecodingError> {
1295        let info = self.info.as_mut().unwrap();
1296        let mut buf = &self.current_chunk.raw_bytes[..];
1297
1298        // read profile name
1299        let _: u8 = buf.read_be()?;
1300        for _ in 1..80 {
1301            let raw: u8 = buf.read_be()?;
1302            if raw == 0 {
1303                break;
1304            }
1305        }
1306
1307        match buf.read_be()? {
1308            // compression method
1309            0u8 => (),
1310            n => {
1311                return Err(DecodingError::Format(
1312                    FormatErrorInner::UnknownCompressionMethod(n).into(),
1313                ))
1314            }
1315        }
1316
1317        match fdeflate::decompress_to_vec_bounded(buf, self.limits.bytes) {
1318            Ok(profile) => {
1319                self.limits.reserve_bytes(profile.len())?;
1320                info.icc_profile = Some(Cow::Owned(profile));
1321            }
1322            Err(fdeflate::BoundedDecompressionError::DecompressionError { inner: err }) => {
1323                return Err(DecodingError::Format(
1324                    FormatErrorInner::CorruptFlateStream { err }.into(),
1325                ))
1326            }
1327            Err(fdeflate::BoundedDecompressionError::OutputTooLarge { .. }) => {
1328                return Err(DecodingError::LimitsExceeded);
1329            }
1330        }
1331
1332        Ok(())
1333    }
1334
1335    fn parse_ihdr(&mut self) -> Result<Decoded, DecodingError> {
1336        if self.info.is_some() {
1337            return Err(DecodingError::Format(
1338                FormatErrorInner::DuplicateChunk { kind: IHDR }.into(),
1339            ));
1340        }
1341        let mut buf = &self.current_chunk.raw_bytes[..];
1342        let width = buf.read_be()?;
1343        let height = buf.read_be()?;
1344        if width == 0 || height == 0 {
1345            return Err(DecodingError::Format(
1346                FormatErrorInner::InvalidDimensions.into(),
1347            ));
1348        }
1349        let bit_depth = buf.read_be()?;
1350        let bit_depth = match BitDepth::from_u8(bit_depth) {
1351            Some(bits) => bits,
1352            None => {
1353                return Err(DecodingError::Format(
1354                    FormatErrorInner::InvalidBitDepth(bit_depth).into(),
1355                ))
1356            }
1357        };
1358        let color_type = buf.read_be()?;
1359        let color_type = match ColorType::from_u8(color_type) {
1360            Some(color_type) => {
1361                if color_type.is_combination_invalid(bit_depth) {
1362                    return Err(DecodingError::Format(
1363                        FormatErrorInner::InvalidColorBitDepth {
1364                            color_type,
1365                            bit_depth,
1366                        }
1367                        .into(),
1368                    ));
1369                } else {
1370                    color_type
1371                }
1372            }
1373            None => {
1374                return Err(DecodingError::Format(
1375                    FormatErrorInner::InvalidColorType(color_type).into(),
1376                ))
1377            }
1378        };
1379        match buf.read_be()? {
1380            // compression method
1381            0u8 => (),
1382            n => {
1383                return Err(DecodingError::Format(
1384                    FormatErrorInner::UnknownCompressionMethod(n).into(),
1385                ))
1386            }
1387        }
1388        match buf.read_be()? {
1389            // filter method
1390            0u8 => (),
1391            n => {
1392                return Err(DecodingError::Format(
1393                    FormatErrorInner::UnknownFilterMethod(n).into(),
1394                ))
1395            }
1396        }
1397        let interlaced = match buf.read_be()? {
1398            0u8 => false,
1399            1 => true,
1400            n => {
1401                return Err(DecodingError::Format(
1402                    FormatErrorInner::UnknownInterlaceMethod(n).into(),
1403                ))
1404            }
1405        };
1406
1407        if let Some(mut raw_row_len) = color_type.checked_raw_row_length(bit_depth, width) {
1408            if interlaced {
1409                // This overshoots, but overestimating should be fine.
1410                // TODO: Calculate **exact** IDAT size for interlaced images.
1411                raw_row_len = raw_row_len.saturating_mul(2);
1412            }
1413            self.inflater
1414                .set_max_total_output((height as usize).saturating_mul(raw_row_len));
1415        }
1416
1417        self.info = Some(Info {
1418            width,
1419            height,
1420            bit_depth,
1421            color_type,
1422            interlaced,
1423            ..Default::default()
1424        });
1425
1426        Ok(Decoded::Header(
1427            width, height, bit_depth, color_type, interlaced,
1428        ))
1429    }
1430
1431    fn split_keyword(buf: &[u8]) -> Result<(&[u8], &[u8]), DecodingError> {
1432        let null_byte_index = buf
1433            .iter()
1434            .position(|&b| b == 0)
1435            .ok_or_else(|| DecodingError::from(TextDecodingError::MissingNullSeparator))?;
1436
1437        if null_byte_index == 0 || null_byte_index > 79 {
1438            return Err(DecodingError::from(TextDecodingError::InvalidKeywordSize));
1439        }
1440
1441        Ok((&buf[..null_byte_index], &buf[null_byte_index + 1..]))
1442    }
1443
1444    fn parse_text(&mut self) -> Result<Decoded, DecodingError> {
1445        let buf = &self.current_chunk.raw_bytes[..];
1446        self.limits.reserve_bytes(buf.len())?;
1447
1448        let (keyword_slice, value_slice) = Self::split_keyword(buf)?;
1449
1450        self.info
1451            .as_mut()
1452            .unwrap()
1453            .uncompressed_latin1_text
1454            .push(TEXtChunk::decode(keyword_slice, value_slice).map_err(DecodingError::from)?);
1455
1456        Ok(Decoded::Nothing)
1457    }
1458
1459    fn parse_ztxt(&mut self) -> Result<Decoded, DecodingError> {
1460        let buf = &self.current_chunk.raw_bytes[..];
1461        self.limits.reserve_bytes(buf.len())?;
1462
1463        let (keyword_slice, value_slice) = Self::split_keyword(buf)?;
1464
1465        let compression_method = *value_slice
1466            .first()
1467            .ok_or_else(|| DecodingError::from(TextDecodingError::InvalidCompressionMethod))?;
1468
1469        let text_slice = &value_slice[1..];
1470
1471        self.info.as_mut().unwrap().compressed_latin1_text.push(
1472            ZTXtChunk::decode(keyword_slice, compression_method, text_slice)
1473                .map_err(DecodingError::from)?,
1474        );
1475
1476        Ok(Decoded::Nothing)
1477    }
1478
1479    fn parse_itxt(&mut self) -> Result<Decoded, DecodingError> {
1480        let buf = &self.current_chunk.raw_bytes[..];
1481        self.limits.reserve_bytes(buf.len())?;
1482
1483        let (keyword_slice, value_slice) = Self::split_keyword(buf)?;
1484
1485        let compression_flag = *value_slice
1486            .first()
1487            .ok_or_else(|| DecodingError::from(TextDecodingError::MissingCompressionFlag))?;
1488
1489        let compression_method = *value_slice
1490            .get(1)
1491            .ok_or_else(|| DecodingError::from(TextDecodingError::InvalidCompressionMethod))?;
1492
1493        let second_null_byte_index = value_slice[2..]
1494            .iter()
1495            .position(|&b| b == 0)
1496            .ok_or_else(|| DecodingError::from(TextDecodingError::MissingNullSeparator))?
1497            + 2;
1498
1499        let language_tag_slice = &value_slice[2..second_null_byte_index];
1500
1501        let third_null_byte_index = value_slice[second_null_byte_index + 1..]
1502            .iter()
1503            .position(|&b| b == 0)
1504            .ok_or_else(|| DecodingError::from(TextDecodingError::MissingNullSeparator))?
1505            + (second_null_byte_index + 1);
1506
1507        let translated_keyword_slice =
1508            &value_slice[second_null_byte_index + 1..third_null_byte_index];
1509
1510        let text_slice = &value_slice[third_null_byte_index + 1..];
1511
1512        self.info.as_mut().unwrap().utf8_text.push(
1513            ITXtChunk::decode(
1514                keyword_slice,
1515                compression_flag,
1516                compression_method,
1517                language_tag_slice,
1518                translated_keyword_slice,
1519                text_slice,
1520            )
1521            .map_err(DecodingError::from)?,
1522        );
1523
1524        Ok(Decoded::Nothing)
1525    }
1526}
1527
1528impl Info<'_> {
1529    fn validate(&self, fc: &FrameControl) -> Result<(), DecodingError> {
1530        if fc.width == 0 || fc.height == 0 {
1531            return Err(DecodingError::Format(
1532                FormatErrorInner::InvalidDimensions.into(),
1533            ));
1534        }
1535
1536        // Validate mathematically: fc.width + fc.x_offset <= self.width
1537        let in_x_bounds = Some(fc.width) <= self.width.checked_sub(fc.x_offset);
1538        // Validate mathematically: fc.height + fc.y_offset <= self.height
1539        let in_y_bounds = Some(fc.height) <= self.height.checked_sub(fc.y_offset);
1540
1541        if !in_x_bounds || !in_y_bounds {
1542            return Err(DecodingError::Format(
1543                // TODO: do we want to display the bad bounds?
1544                FormatErrorInner::BadSubFrameBounds {}.into(),
1545            ));
1546        }
1547
1548        Ok(())
1549    }
1550}
1551
1552impl Default for StreamingDecoder {
1553    fn default() -> Self {
1554        Self::new()
1555    }
1556}
1557
1558impl Default for ChunkState {
1559    fn default() -> Self {
1560        ChunkState {
1561            type_: ChunkType([0; 4]),
1562            crc: Crc32::new(),
1563            remaining: 0,
1564            raw_bytes: Vec::with_capacity(CHUNK_BUFFER_SIZE),
1565        }
1566    }
1567}
1568
1569#[cfg(test)]
1570mod tests {
1571    use super::ScaledFloat;
1572    use super::SourceChromaticities;
1573    use crate::test_utils::*;
1574    use crate::{Decoder, DecodingError, Reader};
1575    use byteorder::WriteBytesExt;
1576    use std::cell::RefCell;
1577    use std::fs::File;
1578    use std::io::{ErrorKind, Read, Write};
1579    use std::rc::Rc;
1580
1581    #[test]
1582    fn image_gamma() -> Result<(), ()> {
1583        fn trial(path: &str, expected: Option<ScaledFloat>) {
1584            let decoder = crate::Decoder::new(File::open(path).unwrap());
1585            let reader = decoder.read_info().unwrap();
1586            let actual: Option<ScaledFloat> = reader.info().source_gamma;
1587            assert!(actual == expected);
1588        }
1589        trial("tests/pngsuite/f00n0g08.png", None);
1590        trial("tests/pngsuite/f00n2c08.png", None);
1591        trial("tests/pngsuite/f01n0g08.png", None);
1592        trial("tests/pngsuite/f01n2c08.png", None);
1593        trial("tests/pngsuite/f02n0g08.png", None);
1594        trial("tests/pngsuite/f02n2c08.png", None);
1595        trial("tests/pngsuite/f03n0g08.png", None);
1596        trial("tests/pngsuite/f03n2c08.png", None);
1597        trial("tests/pngsuite/f04n0g08.png", None);
1598        trial("tests/pngsuite/f04n2c08.png", None);
1599        trial("tests/pngsuite/f99n0g04.png", None);
1600        trial("tests/pngsuite/tm3n3p02.png", None);
1601        trial("tests/pngsuite/g03n0g16.png", Some(ScaledFloat::new(0.35)));
1602        trial("tests/pngsuite/g03n2c08.png", Some(ScaledFloat::new(0.35)));
1603        trial("tests/pngsuite/g03n3p04.png", Some(ScaledFloat::new(0.35)));
1604        trial("tests/pngsuite/g04n0g16.png", Some(ScaledFloat::new(0.45)));
1605        trial("tests/pngsuite/g04n2c08.png", Some(ScaledFloat::new(0.45)));
1606        trial("tests/pngsuite/g04n3p04.png", Some(ScaledFloat::new(0.45)));
1607        trial("tests/pngsuite/g05n0g16.png", Some(ScaledFloat::new(0.55)));
1608        trial("tests/pngsuite/g05n2c08.png", Some(ScaledFloat::new(0.55)));
1609        trial("tests/pngsuite/g05n3p04.png", Some(ScaledFloat::new(0.55)));
1610        trial("tests/pngsuite/g07n0g16.png", Some(ScaledFloat::new(0.7)));
1611        trial("tests/pngsuite/g07n2c08.png", Some(ScaledFloat::new(0.7)));
1612        trial("tests/pngsuite/g07n3p04.png", Some(ScaledFloat::new(0.7)));
1613        trial("tests/pngsuite/g10n0g16.png", Some(ScaledFloat::new(1.0)));
1614        trial("tests/pngsuite/g10n2c08.png", Some(ScaledFloat::new(1.0)));
1615        trial("tests/pngsuite/g10n3p04.png", Some(ScaledFloat::new(1.0)));
1616        trial("tests/pngsuite/g25n0g16.png", Some(ScaledFloat::new(2.5)));
1617        trial("tests/pngsuite/g25n2c08.png", Some(ScaledFloat::new(2.5)));
1618        trial("tests/pngsuite/g25n3p04.png", Some(ScaledFloat::new(2.5)));
1619        Ok(())
1620    }
1621
1622    #[test]
1623    fn image_source_chromaticities() -> Result<(), ()> {
1624        fn trial(path: &str, expected: Option<SourceChromaticities>) {
1625            let decoder = crate::Decoder::new(File::open(path).unwrap());
1626            let reader = decoder.read_info().unwrap();
1627            let actual: Option<SourceChromaticities> = reader.info().source_chromaticities;
1628            assert!(actual == expected);
1629        }
1630        trial(
1631            "tests/pngsuite/ccwn2c08.png",
1632            Some(SourceChromaticities::new(
1633                (0.3127, 0.3290),
1634                (0.64, 0.33),
1635                (0.30, 0.60),
1636                (0.15, 0.06),
1637            )),
1638        );
1639        trial(
1640            "tests/pngsuite/ccwn3p08.png",
1641            Some(SourceChromaticities::new(
1642                (0.3127, 0.3290),
1643                (0.64, 0.33),
1644                (0.30, 0.60),
1645                (0.15, 0.06),
1646            )),
1647        );
1648        trial("tests/pngsuite/basi0g01.png", None);
1649        trial("tests/pngsuite/basi0g02.png", None);
1650        trial("tests/pngsuite/basi0g04.png", None);
1651        trial("tests/pngsuite/basi0g08.png", None);
1652        trial("tests/pngsuite/basi0g16.png", None);
1653        trial("tests/pngsuite/basi2c08.png", None);
1654        trial("tests/pngsuite/basi2c16.png", None);
1655        trial("tests/pngsuite/basi3p01.png", None);
1656        trial("tests/pngsuite/basi3p02.png", None);
1657        trial("tests/pngsuite/basi3p04.png", None);
1658        trial("tests/pngsuite/basi3p08.png", None);
1659        trial("tests/pngsuite/basi4a08.png", None);
1660        trial("tests/pngsuite/basi4a16.png", None);
1661        trial("tests/pngsuite/basi6a08.png", None);
1662        trial("tests/pngsuite/basi6a16.png", None);
1663        trial("tests/pngsuite/basn0g01.png", None);
1664        trial("tests/pngsuite/basn0g02.png", None);
1665        trial("tests/pngsuite/basn0g04.png", None);
1666        trial("tests/pngsuite/basn0g08.png", None);
1667        trial("tests/pngsuite/basn0g16.png", None);
1668        trial("tests/pngsuite/basn2c08.png", None);
1669        trial("tests/pngsuite/basn2c16.png", None);
1670        trial("tests/pngsuite/basn3p01.png", None);
1671        trial("tests/pngsuite/basn3p02.png", None);
1672        trial("tests/pngsuite/basn3p04.png", None);
1673        trial("tests/pngsuite/basn3p08.png", None);
1674        trial("tests/pngsuite/basn4a08.png", None);
1675        trial("tests/pngsuite/basn4a16.png", None);
1676        trial("tests/pngsuite/basn6a08.png", None);
1677        trial("tests/pngsuite/basn6a16.png", None);
1678        trial("tests/pngsuite/bgai4a08.png", None);
1679        trial("tests/pngsuite/bgai4a16.png", None);
1680        trial("tests/pngsuite/bgan6a08.png", None);
1681        trial("tests/pngsuite/bgan6a16.png", None);
1682        trial("tests/pngsuite/bgbn4a08.png", None);
1683        trial("tests/pngsuite/bggn4a16.png", None);
1684        trial("tests/pngsuite/bgwn6a08.png", None);
1685        trial("tests/pngsuite/bgyn6a16.png", None);
1686        trial("tests/pngsuite/cdfn2c08.png", None);
1687        trial("tests/pngsuite/cdhn2c08.png", None);
1688        trial("tests/pngsuite/cdsn2c08.png", None);
1689        trial("tests/pngsuite/cdun2c08.png", None);
1690        trial("tests/pngsuite/ch1n3p04.png", None);
1691        trial("tests/pngsuite/ch2n3p08.png", None);
1692        trial("tests/pngsuite/cm0n0g04.png", None);
1693        trial("tests/pngsuite/cm7n0g04.png", None);
1694        trial("tests/pngsuite/cm9n0g04.png", None);
1695        trial("tests/pngsuite/cs3n2c16.png", None);
1696        trial("tests/pngsuite/cs3n3p08.png", None);
1697        trial("tests/pngsuite/cs5n2c08.png", None);
1698        trial("tests/pngsuite/cs5n3p08.png", None);
1699        trial("tests/pngsuite/cs8n2c08.png", None);
1700        trial("tests/pngsuite/cs8n3p08.png", None);
1701        trial("tests/pngsuite/ct0n0g04.png", None);
1702        trial("tests/pngsuite/ct1n0g04.png", None);
1703        trial("tests/pngsuite/cten0g04.png", None);
1704        trial("tests/pngsuite/ctfn0g04.png", None);
1705        trial("tests/pngsuite/ctgn0g04.png", None);
1706        trial("tests/pngsuite/cthn0g04.png", None);
1707        trial("tests/pngsuite/ctjn0g04.png", None);
1708        trial("tests/pngsuite/ctzn0g04.png", None);
1709        trial("tests/pngsuite/f00n0g08.png", None);
1710        trial("tests/pngsuite/f00n2c08.png", None);
1711        trial("tests/pngsuite/f01n0g08.png", None);
1712        trial("tests/pngsuite/f01n2c08.png", None);
1713        trial("tests/pngsuite/f02n0g08.png", None);
1714        trial("tests/pngsuite/f02n2c08.png", None);
1715        trial("tests/pngsuite/f03n0g08.png", None);
1716        trial("tests/pngsuite/f03n2c08.png", None);
1717        trial("tests/pngsuite/f04n0g08.png", None);
1718        trial("tests/pngsuite/f04n2c08.png", None);
1719        trial("tests/pngsuite/f99n0g04.png", None);
1720        trial("tests/pngsuite/g03n0g16.png", None);
1721        trial("tests/pngsuite/g03n2c08.png", None);
1722        trial("tests/pngsuite/g03n3p04.png", None);
1723        trial("tests/pngsuite/g04n0g16.png", None);
1724        trial("tests/pngsuite/g04n2c08.png", None);
1725        trial("tests/pngsuite/g04n3p04.png", None);
1726        trial("tests/pngsuite/g05n0g16.png", None);
1727        trial("tests/pngsuite/g05n2c08.png", None);
1728        trial("tests/pngsuite/g05n3p04.png", None);
1729        trial("tests/pngsuite/g07n0g16.png", None);
1730        trial("tests/pngsuite/g07n2c08.png", None);
1731        trial("tests/pngsuite/g07n3p04.png", None);
1732        trial("tests/pngsuite/g10n0g16.png", None);
1733        trial("tests/pngsuite/g10n2c08.png", None);
1734        trial("tests/pngsuite/g10n3p04.png", None);
1735        trial("tests/pngsuite/g25n0g16.png", None);
1736        trial("tests/pngsuite/g25n2c08.png", None);
1737        trial("tests/pngsuite/g25n3p04.png", None);
1738        trial("tests/pngsuite/oi1n0g16.png", None);
1739        trial("tests/pngsuite/oi1n2c16.png", None);
1740        trial("tests/pngsuite/oi2n0g16.png", None);
1741        trial("tests/pngsuite/oi2n2c16.png", None);
1742        trial("tests/pngsuite/oi4n0g16.png", None);
1743        trial("tests/pngsuite/oi4n2c16.png", None);
1744        trial("tests/pngsuite/oi9n0g16.png", None);
1745        trial("tests/pngsuite/oi9n2c16.png", None);
1746        trial("tests/pngsuite/PngSuite.png", None);
1747        trial("tests/pngsuite/pp0n2c16.png", None);
1748        trial("tests/pngsuite/pp0n6a08.png", None);
1749        trial("tests/pngsuite/ps1n0g08.png", None);
1750        trial("tests/pngsuite/ps1n2c16.png", None);
1751        trial("tests/pngsuite/ps2n0g08.png", None);
1752        trial("tests/pngsuite/ps2n2c16.png", None);
1753        trial("tests/pngsuite/s01i3p01.png", None);
1754        trial("tests/pngsuite/s01n3p01.png", None);
1755        trial("tests/pngsuite/s02i3p01.png", None);
1756        trial("tests/pngsuite/s02n3p01.png", None);
1757        trial("tests/pngsuite/s03i3p01.png", None);
1758        trial("tests/pngsuite/s03n3p01.png", None);
1759        trial("tests/pngsuite/s04i3p01.png", None);
1760        trial("tests/pngsuite/s04n3p01.png", None);
1761        trial("tests/pngsuite/s05i3p02.png", None);
1762        trial("tests/pngsuite/s05n3p02.png", None);
1763        trial("tests/pngsuite/s06i3p02.png", None);
1764        trial("tests/pngsuite/s06n3p02.png", None);
1765        trial("tests/pngsuite/s07i3p02.png", None);
1766        trial("tests/pngsuite/s07n3p02.png", None);
1767        trial("tests/pngsuite/s08i3p02.png", None);
1768        trial("tests/pngsuite/s08n3p02.png", None);
1769        trial("tests/pngsuite/s09i3p02.png", None);
1770        trial("tests/pngsuite/s09n3p02.png", None);
1771        trial("tests/pngsuite/s32i3p04.png", None);
1772        trial("tests/pngsuite/s32n3p04.png", None);
1773        trial("tests/pngsuite/s33i3p04.png", None);
1774        trial("tests/pngsuite/s33n3p04.png", None);
1775        trial("tests/pngsuite/s34i3p04.png", None);
1776        trial("tests/pngsuite/s34n3p04.png", None);
1777        trial("tests/pngsuite/s35i3p04.png", None);
1778        trial("tests/pngsuite/s35n3p04.png", None);
1779        trial("tests/pngsuite/s36i3p04.png", None);
1780        trial("tests/pngsuite/s36n3p04.png", None);
1781        trial("tests/pngsuite/s37i3p04.png", None);
1782        trial("tests/pngsuite/s37n3p04.png", None);
1783        trial("tests/pngsuite/s38i3p04.png", None);
1784        trial("tests/pngsuite/s38n3p04.png", None);
1785        trial("tests/pngsuite/s39i3p04.png", None);
1786        trial("tests/pngsuite/s39n3p04.png", None);
1787        trial("tests/pngsuite/s40i3p04.png", None);
1788        trial("tests/pngsuite/s40n3p04.png", None);
1789        trial("tests/pngsuite/tbbn0g04.png", None);
1790        trial("tests/pngsuite/tbbn2c16.png", None);
1791        trial("tests/pngsuite/tbbn3p08.png", None);
1792        trial("tests/pngsuite/tbgn2c16.png", None);
1793        trial("tests/pngsuite/tbgn3p08.png", None);
1794        trial("tests/pngsuite/tbrn2c08.png", None);
1795        trial("tests/pngsuite/tbwn0g16.png", None);
1796        trial("tests/pngsuite/tbwn3p08.png", None);
1797        trial("tests/pngsuite/tbyn3p08.png", None);
1798        trial("tests/pngsuite/tm3n3p02.png", None);
1799        trial("tests/pngsuite/tp0n0g08.png", None);
1800        trial("tests/pngsuite/tp0n2c08.png", None);
1801        trial("tests/pngsuite/tp0n3p08.png", None);
1802        trial("tests/pngsuite/tp1n3p08.png", None);
1803        trial("tests/pngsuite/z00n2c08.png", None);
1804        trial("tests/pngsuite/z03n2c08.png", None);
1805        trial("tests/pngsuite/z06n2c08.png", None);
1806        Ok(())
1807    }
1808
1809    /// Test handling of a PNG file that contains *two* iCCP chunks.
1810    /// This is a regression test for https://github.com/image-rs/image/issues/1825.
1811    #[test]
1812    fn test_two_iccp_chunks() {
1813        // The test file has been taken from
1814        // https://github.com/image-rs/image/issues/1825#issuecomment-1321798639,
1815        // but the 2nd iCCP chunk has been altered manually (see the 2nd comment below for more
1816        // details).
1817        let decoder = crate::Decoder::new(File::open("tests/bugfixes/issue#1825.png").unwrap());
1818        let reader = decoder.read_info().unwrap();
1819        let icc_profile = reader.info().icc_profile.clone().unwrap().into_owned();
1820
1821        // Assert that the contents of the *first* iCCP chunk are returned.
1822        //
1823        // Note that the 2nd chunk in the test file has been manually altered to have a different
1824        // content (`b"test iccp contents"`) which would have a different CRC (797351983).
1825        assert_eq!(4070462061, crc32fast::hash(&icc_profile));
1826    }
1827
1828    #[test]
1829    fn test_png_with_broken_iccp() {
1830        let decoder = crate::Decoder::new(File::open("tests/iccp/broken_iccp.png").unwrap());
1831        assert!(decoder.read_info().is_ok());
1832        let mut decoder = crate::Decoder::new(File::open("tests/iccp/broken_iccp.png").unwrap());
1833        decoder.set_ignore_iccp_chunk(true);
1834        assert!(decoder.read_info().is_ok());
1835    }
1836
1837    /// Writes an acTL chunk.
1838    /// See https://wiki.mozilla.org/APNG_Specification#.60acTL.60:_The_Animation_Control_Chunk
1839    fn write_actl(w: &mut impl Write, animation: &crate::AnimationControl) {
1840        let mut data = Vec::new();
1841        data.write_u32::<byteorder::BigEndian>(animation.num_frames)
1842            .unwrap();
1843        data.write_u32::<byteorder::BigEndian>(animation.num_plays)
1844            .unwrap();
1845        write_chunk(w, b"acTL", &data);
1846    }
1847
1848    /// Writes an fcTL chunk.
1849    /// See https://wiki.mozilla.org/APNG_Specification#.60fcTL.60:_The_Frame_Control_Chunk
1850    fn write_fctl(w: &mut impl Write, frame: &crate::FrameControl) {
1851        let mut data = Vec::new();
1852        data.write_u32::<byteorder::BigEndian>(frame.sequence_number)
1853            .unwrap();
1854        data.write_u32::<byteorder::BigEndian>(frame.width).unwrap();
1855        data.write_u32::<byteorder::BigEndian>(frame.height)
1856            .unwrap();
1857        data.write_u32::<byteorder::BigEndian>(frame.x_offset)
1858            .unwrap();
1859        data.write_u32::<byteorder::BigEndian>(frame.y_offset)
1860            .unwrap();
1861        data.write_u16::<byteorder::BigEndian>(frame.delay_num)
1862            .unwrap();
1863        data.write_u16::<byteorder::BigEndian>(frame.delay_den)
1864            .unwrap();
1865        data.write_u8(frame.dispose_op as u8).unwrap();
1866        data.write_u8(frame.blend_op as u8).unwrap();
1867        write_chunk(w, b"fcTL", &data);
1868    }
1869
1870    /// Writes an fdAT chunk.
1871    /// See https://wiki.mozilla.org/APNG_Specification#.60fdAT.60:_The_Frame_Data_Chunk
1872    fn write_fdat(w: &mut impl Write, sequence_number: u32, image_data: &[u8]) {
1873        let mut data = Vec::new();
1874        data.write_u32::<byteorder::BigEndian>(sequence_number)
1875            .unwrap();
1876        data.write_all(image_data).unwrap();
1877        write_chunk(w, b"fdAT", &data);
1878    }
1879
1880    /// Writes PNG signature and chunks that can precede an fdAT chunk that is expected
1881    /// to have
1882    /// - `sequence_number` set to 0
1883    /// - image data with rgba8 pixels in a `width` by `width` image
1884    fn write_fdat_prefix(w: &mut impl Write, num_frames: u32, width: u32) {
1885        write_png_sig(w);
1886        write_rgba8_ihdr_with_width(w, width);
1887        write_actl(
1888            w,
1889            &crate::AnimationControl {
1890                num_frames,
1891                num_plays: 0,
1892            },
1893        );
1894
1895        let mut fctl = crate::FrameControl {
1896            width,
1897            height: width,
1898            ..Default::default()
1899        };
1900        write_fctl(w, &fctl);
1901        write_rgba8_idats(w, width, 0x7fffffff);
1902
1903        fctl.sequence_number += 1;
1904        write_fctl(w, &fctl);
1905    }
1906
1907    #[test]
1908    fn test_fdat_chunk_payload_length_0() {
1909        let mut png = Vec::new();
1910        write_fdat_prefix(&mut png, 2, 8);
1911        write_chunk(&mut png, b"fdAT", &[]);
1912
1913        let decoder = Decoder::new(png.as_slice());
1914        let mut reader = decoder.read_info().unwrap();
1915        let mut buf = vec![0; reader.output_buffer_size()];
1916        reader.next_frame(&mut buf).unwrap();
1917
1918        // 0-length fdAT should result in an error.
1919        let err = reader.next_frame(&mut buf).unwrap_err();
1920        assert!(matches!(&err, DecodingError::Format(_)));
1921        let msg = format!("{err}");
1922        assert_eq!("fdAT chunk shorter than 4 bytes", msg);
1923    }
1924
1925    #[test]
1926    fn test_fdat_chunk_payload_length_3() {
1927        let mut png = Vec::new();
1928        write_fdat_prefix(&mut png, 2, 8);
1929        write_chunk(&mut png, b"fdAT", &[1, 0, 0]);
1930
1931        let decoder = Decoder::new(png.as_slice());
1932        let mut reader = decoder.read_info().unwrap();
1933        let mut buf = vec![0; reader.output_buffer_size()];
1934        reader.next_frame(&mut buf).unwrap();
1935
1936        // 3-bytes-long fdAT should result in an error.
1937        let err = reader.next_frame(&mut buf).unwrap_err();
1938        assert!(matches!(&err, DecodingError::Format(_)));
1939        let msg = format!("{err}");
1940        assert_eq!("fdAT chunk shorter than 4 bytes", msg);
1941    }
1942
1943    #[test]
1944    fn test_frame_split_across_two_fdat_chunks() {
1945        // Generate test data where the 2nd animation frame is split across 2 fdAT chunks.
1946        //
1947        // This is similar to the example given in
1948        // https://wiki.mozilla.org/APNG_Specification#Chunk_Sequence_Numbers:
1949        //
1950        // ```
1951        //    Sequence number    Chunk
1952        //    (none)             `acTL`
1953        //    0                  `fcTL` first frame
1954        //    (none)             `IDAT` first frame / default image
1955        //    1                  `fcTL` second frame
1956        //    2                  first `fdAT` for second frame
1957        //    3                  second `fdAT` for second frame
1958        // ```
1959        let png = {
1960            let mut png = Vec::new();
1961            write_fdat_prefix(&mut png, 2, 8);
1962            let image_data = generate_rgba8_with_width_and_height(8, 8);
1963            write_fdat(&mut png, 2, &image_data[..30]);
1964            write_fdat(&mut png, 3, &image_data[30..]);
1965            write_iend(&mut png);
1966            png
1967        };
1968
1969        // Start decoding.
1970        let decoder = Decoder::new(png.as_slice());
1971        let mut reader = decoder.read_info().unwrap();
1972        let mut buf = vec![0; reader.output_buffer_size()];
1973        let Some(animation_control) = reader.info().animation_control else {
1974            panic!("No acTL");
1975        };
1976        assert_eq!(animation_control.num_frames, 2);
1977
1978        // Process the 1st animation frame.
1979        let first_frame: Vec<u8>;
1980        {
1981            reader.next_frame(&mut buf).unwrap();
1982            first_frame = buf.clone();
1983
1984            // Note that the doc comment of `Reader::next_frame` says that "[...]
1985            // can be checked afterwards by calling `info` **after** a successful call and
1986            // inspecting the `frame_control` data.".  (Note the **emphasis** on "after".)
1987            let Some(frame_control) = reader.info().frame_control else {
1988                panic!("No fcTL (1st frame)");
1989            };
1990            // The sequence number is taken from the `fcTL` chunk that comes before the `IDAT`
1991            // chunk.
1992            assert_eq!(frame_control.sequence_number, 0);
1993        }
1994
1995        // Process the 2nd animation frame.
1996        let second_frame: Vec<u8>;
1997        {
1998            reader.next_frame(&mut buf).unwrap();
1999            second_frame = buf.clone();
2000
2001            // Same as above - updated `frame_control` is available *after* the `next_frame` call.
2002            let Some(frame_control) = reader.info().frame_control else {
2003                panic!("No fcTL (2nd frame)");
2004            };
2005            // The sequence number is taken from the `fcTL` chunk that comes before the two `fdAT`
2006            // chunks.  Note that sequence numbers inside `fdAT` chunks are not publicly exposed
2007            // (but they are still checked when decoding to verify that they are sequential).
2008            assert_eq!(frame_control.sequence_number, 1);
2009        }
2010
2011        assert_eq!(first_frame, second_frame);
2012    }
2013
2014    #[test]
2015    fn test_idat_bigger_than_image_size_from_ihdr() {
2016        let png = {
2017            let mut png = Vec::new();
2018            write_png_sig(&mut png);
2019            write_rgba8_ihdr_with_width(&mut png, 8);
2020
2021            // Here we want to test an invalid image where the `IDAT` chunk contains more data
2022            // (data for 8x256 image) than declared in the `IHDR` chunk (which only describes an
2023            // 8x8 image).
2024            write_chunk(
2025                &mut png,
2026                b"IDAT",
2027                &generate_rgba8_with_width_and_height(8, 256),
2028            );
2029
2030            write_iend(&mut png);
2031            png
2032        };
2033        let decoder = Decoder::new(png.as_slice());
2034        let mut reader = decoder.read_info().unwrap();
2035        let mut buf = vec![0; reader.output_buffer_size()];
2036
2037        // TODO: Should this return an error instead?  For now let's just have test assertions for
2038        // the current behavior.
2039        reader.next_frame(&mut buf).unwrap();
2040        assert_eq!(3093270825, crc32fast::hash(&buf));
2041    }
2042
2043    /// `StremingInput` can be used by tests to simulate a streaming input
2044    /// (e.g. a slow http response, where all bytes are not immediately available).
2045    #[derive(Clone)]
2046    struct StreamingInput(Rc<RefCell<StreamingInputState>>);
2047
2048    struct StreamingInputState {
2049        full_input: Vec<u8>,
2050        current_pos: usize,
2051        available_len: usize,
2052    }
2053
2054    impl StreamingInput {
2055        fn new(full_input: Vec<u8>) -> Self {
2056            Self(Rc::new(RefCell::new(StreamingInputState {
2057                full_input,
2058                current_pos: 0,
2059                available_len: 0,
2060            })))
2061        }
2062
2063        fn with_noncompressed_png(width: u32, idat_size: usize) -> Self {
2064            let mut png = Vec::new();
2065            write_noncompressed_png(&mut png, width, idat_size);
2066            Self::new(png)
2067        }
2068
2069        fn expose_next_byte(&self) {
2070            let mut state = self.0.borrow_mut();
2071            assert!(state.available_len < state.full_input.len());
2072            state.available_len += 1;
2073        }
2074
2075        fn stream_input_until_reader_is_available(&self) -> Reader<StreamingInput> {
2076            loop {
2077                self.0.borrow_mut().current_pos = 0;
2078                match Decoder::new(self.clone()).read_info() {
2079                    Ok(reader) => {
2080                        break reader;
2081                    }
2082                    Err(DecodingError::IoError(e)) if e.kind() == ErrorKind::UnexpectedEof => {
2083                        self.expose_next_byte();
2084                    }
2085                    _ => panic!("Unexpected error"),
2086                }
2087            }
2088        }
2089
2090        fn decode_full_input<F, R>(&self, f: F) -> R
2091        where
2092            F: FnOnce(Reader<&[u8]>) -> R,
2093        {
2094            let state = self.0.borrow();
2095            let decoder = Decoder::new(state.full_input.as_slice());
2096            f(decoder.read_info().unwrap())
2097        }
2098    }
2099
2100    impl Read for StreamingInput {
2101        fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
2102            let mut state = self.0.borrow_mut();
2103            let mut available_bytes = &state.full_input[state.current_pos..state.available_len];
2104            let number_of_read_bytes = available_bytes.read(buf)?;
2105            state.current_pos += number_of_read_bytes;
2106            assert!(state.current_pos <= state.available_len);
2107            Ok(number_of_read_bytes)
2108        }
2109    }
2110
2111    /// Test resuming/retrying `Reader.next_frame` after `UnexpectedEof`.
2112    #[test]
2113    fn test_streaming_input_and_decoding_via_next_frame() {
2114        const WIDTH: u32 = 16;
2115        const IDAT_SIZE: usize = 512;
2116        let streaming_input = StreamingInput::with_noncompressed_png(WIDTH, IDAT_SIZE);
2117
2118        let (whole_output_info, decoded_from_whole_input) =
2119            streaming_input.decode_full_input(|mut r| {
2120                let mut buf = vec![0; r.output_buffer_size()];
2121                let output_info = r.next_frame(&mut buf).unwrap();
2122                (output_info, buf)
2123            });
2124
2125        let mut png_reader = streaming_input.stream_input_until_reader_is_available();
2126        let mut decoded_from_streaming_input = vec![0; png_reader.output_buffer_size()];
2127        let streaming_output_info = loop {
2128            match png_reader.next_frame(decoded_from_streaming_input.as_mut_slice()) {
2129                Ok(output_info) => break output_info,
2130                Err(DecodingError::IoError(e)) if e.kind() == ErrorKind::UnexpectedEof => {
2131                    streaming_input.expose_next_byte()
2132                }
2133                e => panic!("Unexpected error: {:?}", e),
2134            }
2135        };
2136        assert_eq!(whole_output_info, streaming_output_info);
2137        assert_eq!(
2138            crc32fast::hash(&decoded_from_whole_input),
2139            crc32fast::hash(&decoded_from_streaming_input)
2140        );
2141    }
2142
2143    /// Test resuming/retrying `Reader.next_row` after `UnexpectedEof`.
2144    #[test]
2145    fn test_streaming_input_and_decoding_via_next_row() {
2146        const WIDTH: u32 = 16;
2147        const IDAT_SIZE: usize = 512;
2148        let streaming_input = StreamingInput::with_noncompressed_png(WIDTH, IDAT_SIZE);
2149
2150        let decoded_from_whole_input = streaming_input.decode_full_input(|mut r| {
2151            let mut buf = vec![0; r.output_buffer_size()];
2152            r.next_frame(&mut buf).unwrap();
2153            buf
2154        });
2155
2156        let mut png_reader = streaming_input.stream_input_until_reader_is_available();
2157        let mut decoded_from_streaming_input = Vec::new();
2158        loop {
2159            match png_reader.next_row() {
2160                Ok(None) => break,
2161                Ok(Some(row)) => decoded_from_streaming_input.extend_from_slice(row.data()),
2162                Err(DecodingError::IoError(e)) if e.kind() == ErrorKind::UnexpectedEof => {
2163                    streaming_input.expose_next_byte()
2164                }
2165                e => panic!("Unexpected error: {:?}", e),
2166            }
2167        }
2168        assert_eq!(
2169            crc32fast::hash(&decoded_from_whole_input),
2170            crc32fast::hash(&decoded_from_streaming_input)
2171        );
2172    }
2173
2174    /// Test resuming/retrying `Decoder.read_header_info` after `UnexpectedEof`.
2175    #[test]
2176    fn test_streaming_input_and_reading_header_info() {
2177        const WIDTH: u32 = 16;
2178        const IDAT_SIZE: usize = 512;
2179        let streaming_input = StreamingInput::with_noncompressed_png(WIDTH, IDAT_SIZE);
2180
2181        let info_from_whole_input = streaming_input.decode_full_input(|r| r.info().clone());
2182
2183        let mut decoder = Decoder::new(streaming_input.clone());
2184        let info_from_streaming_input = loop {
2185            match decoder.read_header_info() {
2186                Ok(info) => break info.clone(),
2187                Err(DecodingError::IoError(e)) if e.kind() == ErrorKind::UnexpectedEof => {
2188                    streaming_input.expose_next_byte()
2189                }
2190                e => panic!("Unexpected error: {:?}", e),
2191            }
2192        };
2193
2194        assert_eq!(info_from_whole_input.width, info_from_streaming_input.width);
2195        assert_eq!(
2196            info_from_whole_input.height,
2197            info_from_streaming_input.height
2198        );
2199        assert_eq!(
2200            info_from_whole_input.bit_depth,
2201            info_from_streaming_input.bit_depth
2202        );
2203        assert_eq!(
2204            info_from_whole_input.color_type,
2205            info_from_streaming_input.color_type
2206        );
2207        assert_eq!(
2208            info_from_whole_input.interlaced,
2209            info_from_streaming_input.interlaced
2210        );
2211    }
2212}