diff --git a/jxl/src/api/decoder.rs b/jxl/src/api/decoder.rs index 6090559a0..6e89434e2 100644 --- a/jxl/src/api/decoder.rs +++ b/jxl/src/api/decoder.rs @@ -2034,6 +2034,16 @@ pub(crate) mod tests { } } + /// Regression test for Chromium ClusterFuzz issue 526010666. + #[test] + fn test_flush_pixels_without_pixel_format_no_panic_526010666() { + let mut decoder = JxlDecoderInner::new(JxlDecoderOptions::default()); + let mut pixels = [0u8; 4]; + let output = JxlOutputBuffer::new(&mut pixels, 1, 4); + let err = decoder.flush_pixels(&mut [output]).unwrap_err(); + assert!(matches!(err, crate::error::Error::PixelFormatNotSet)); + } + /// Small regression test for issue #728: squeeze transform boundary bug. #[test] fn test_squeeze_boundary_minimal() { diff --git a/jxl/src/api/inner/codestream_parser/mod.rs b/jxl/src/api/inner/codestream_parser/mod.rs index d26cdad22..161f3561e 100644 --- a/jxl/src/api/inner/codestream_parser/mod.rs +++ b/jxl/src/api/inner/codestream_parser/mod.rs @@ -385,7 +385,9 @@ impl CodestreamParser { do_flush: bool, ) -> Result<()> { if let Some(output_buffers) = &output_buffers { - let px = self.pixel_format.as_ref().unwrap(); + let Some(px) = self.pixel_format.as_ref() else { + return Err(Error::PixelFormatNotSet); + }; let expected_len = std::iter::once(&px.color_data_format) .chain(px.extra_channel_format.iter()) .filter(|x| x.is_some()) diff --git a/jxl/src/error.rs b/jxl/src/error.rs index 5519b6d90..f7047657b 100644 --- a/jxl/src/error.rs +++ b/jxl/src/error.rs @@ -263,6 +263,8 @@ pub enum Error { IccTableSizeExceeded(usize), #[error("I/O error: {0}")] IOError(#[from] std::io::Error), + #[error("Output pixel format is not set")] + PixelFormatNotSet, #[error("Wrong buffer count: {0} buffers given, {1} buffers expected")] WrongBufferCount(usize, usize), #[error("Image is not grayscale, but grayscale output was requested")]