diff --git a/src/reader/decoder.rs b/src/reader/decoder.rs index 2e75da0..4b9a855 100644 --- a/src/reader/decoder.rs +++ b/src/reader/decoder.rs @@ -772,7 +772,7 @@ impl StreamingDecoder { if left > 0 { let n = cmp::min(left, buf.len()); if self.lzw_reader.has_ended() || matches!(write_into, OutputBuffer::None) { - return goto!(n, DecodeSubBlock(0), emit Decoded::Nothing); + return goto!(n, DecodeSubBlock(left - n), emit Decoded::Nothing); } let (mut consumed, bytes_len) = self.lzw_reader.decode_bytes(&buf[..n], write_into)?; diff --git a/tests/stall.rs b/tests/stall.rs index 1e58d65..a25d725 100644 --- a/tests/stall.rs +++ b/tests/stall.rs @@ -1,6 +1,6 @@ #![cfg(feature = "std")] -use std::{fs, sync::mpsc, thread, time::Duration}; +use std::{fs, sync::mpsc, thread, time::Duration, io}; #[test] fn try_decode_crash_regression() { @@ -42,3 +42,38 @@ fn decode(data: &[u8]) -> Result<(), gif::DecodingError> { Ok(()) } + +#[test] +fn one_byte_at_a_time() { + let r = OneByte { + data: include_bytes!("../tests/samples/moon_impact.gif"), + }; + let frames = gif::DecodeOptions::new().read_info(r).unwrap() + .into_iter().enumerate().map(|(n, f)| { + f.expect(&n.to_string()) + }).count(); + assert_eq!(frames, 14); +} + +struct OneByte<'a> { + data: &'a [u8], +} + +impl io::BufRead for OneByte<'_> { + fn fill_buf(&mut self) -> io::Result<&[u8]> { + Ok(&self.data[..self.data.len().min(1)]) + } + fn consume(&mut self, n: usize) { + debug_assert!(n <= 1); + self.data = &self.data[n..]; + } +} + +impl io::Read for OneByte<'_> { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + let n = self.data.len().min(buf.len()).min(1); + buf[..n].copy_from_slice(&self.data[..n]); + self.data = &self.data[n..]; + Ok(n) + } +}