1From 3ef723bdb6f816e0d467aa6cf7739d525857f669 Mon Sep 17 00:00:00 2001
2From: Lukasz Anforowicz <[email protected]>
3Date: Thu, 3 Oct 2024 19:38:26 +0000
4Subject: [PATCH 103/113] Call `finish_decoding` after last `next_row`.
5
6Before this commit, `next_frame` would take care to read till the end of
7an `IDAT`/`fdAT` chunks sequence, by calling
8`self.decoder.finish_decoding` when
9`!self.subframe.consumed_and_flushed`.  `next_row` wouldn't do this and
10therefore the next call to `next_frame` would be temporarily stuck on
11the previous frame (i.e. finishing decoding after the previous frame
12rather than advancing to the next frame).
13
14After this commit, the `finish_decoding` code is extracted to a separate
15helper function that is called by *both* `next_frame` and
16`next_interlaced_row` (once they detect that all rows of a frame have
17been already decoded).
18
19This commit fixes the `test_row_by_row_then_next_frame` unit test.
20---
21 src/decoder/mod.rs    | 25 ++++++++++++++++++++-----
22 src/decoder/stream.rs | 14 +++++++++++---
23 2 files changed, 31 insertions(+), 8 deletions(-)
24
25diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/mod.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/mod.rs
26index 8a76200..56570b3 100644
27--- a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/mod.rs
28+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/mod.rs
29@@ -532,10 +532,7 @@ impl<R: Read> Reader<R> {
30         }
31
32         // Advance over the rest of data for this (sub-)frame.
33-        if !self.subframe.consumed_and_flushed {
34-            self.decoder.finish_decoding()?;
35-            self.subframe.consumed_and_flushed = true;
36-        }
37+        self.finish_decoding()?;
38
39         // Advance our state to expect the next frame.
40         let past_end_subframe = self
41@@ -558,6 +555,21 @@ impl<R: Read> Reader<R> {
42         Ok(output_info)
43     }
44
45+    /// Advance over the rest of data for this (sub-)frame.
46+    /// Called after decoding the last row of a frame.
47+    fn finish_decoding(&mut self) -> Result<(), DecodingError> {
48+        // Double-check that all rows of this frame have been decoded.
49+        assert!(self.subframe.current_interlace_info.is_none());
50+
51+        // Discard the remaining data in the current sequence of `IDAT` or `fdAT` chunks.
52+        if !self.subframe.consumed_and_flushed {
53+            self.decoder.finish_decoding()?;
54+            self.subframe.consumed_and_flushed = true;
55+        }
56+
57+        Ok(())
58+    }
59+
60     /// Returns the next processed row of the image
61     pub fn next_row(&mut self) -> Result<Option<Row>, DecodingError> {
62         self.next_interlaced_row()
63@@ -567,7 +579,10 @@ impl<R: Read> Reader<R> {
64     /// Returns the next processed row of the image
65     pub fn next_interlaced_row(&mut self) -> Result<Option<InterlacedRow>, DecodingError> {
66         let interlace = match self.subframe.current_interlace_info.as_ref() {
67-            None => return Ok(None),
68+            None => {
69+                self.finish_decoding()?;
70+                return Ok(None);
71+            }
72             Some(interlace) => *interlace,
73         };
74         if interlace.line_number() == 0 {
75diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs
76index 9c7e1b6..2607078 100644
77--- a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs
78+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs
79@@ -2431,8 +2431,16 @@ mod tests {
80             .next_frame(&mut buf)
81             .expect("Expecting no error from next_frame call");
82
83-        // TODO: Verify if we have read the next `fcTL` chunk + repopulated `buf`:
84-        //assert_eq!(reader.info().frame_control.as_ref().unwrap().sequence_number, 1);
85-        //assert!(buf.iter().any(|byte| *byte != 0x0f));
86+        // Verify if we have read the next `fcTL` chunk + repopulated `buf`:
87+        assert_eq!(
88+            reader
89+                .info()
90+                .frame_control
91+                .as_ref()
92+                .unwrap()
93+                .sequence_number,
94+            1
95+        );
96+        assert!(buf.iter().any(|byte| *byte != 0x0f));
97     }
98 }
99--
1002.47.0.rc0.187.ge670bccf7e-goog
101
102