#![no_main] extern crate libfuzzer_sys; use libfuzzer_sys::fuzz_target; extern crate png; use std::io::{BufRead, Read, Result}; /// A reader that reads at most `n` bytes. struct SmalBuf { inner: R, cap: usize, } impl SmalBuf { fn new(inner: R, cap: usize) -> Self { SmalBuf { inner, cap } } } impl Read for SmalBuf { fn read(&mut self, buf: &mut [u8]) -> Result { let len = buf.len().min(self.cap); self.inner.read(&mut buf[..len]) } } impl BufRead for SmalBuf { fn fill_buf(&mut self) -> Result<&[u8]> { let buf = self.inner.fill_buf()?; let len = buf.len().min(self.cap); Ok(&buf[..len]) } fn consume(&mut self, amt: usize) { assert!(amt <= self.cap); self.inner.consume(amt) } } fuzz_target!(|data: &[u8]| { // Small limits, we don't need them hopefully. let limits = png::Limits { bytes: 1 << 16 }; let reference = png::Decoder::new_with_limits(data, limits); let smal = png::Decoder::new_with_limits(SmalBuf::new(data, 1), limits); let _ = png_compare(reference, smal); }); #[inline(always)] fn png_compare(reference: png::Decoder, smal: png::Decoder) -> std::result::Result { let mut smal = Some(smal); let (info, mut reference) = reference.read_info().map_err(|_| { assert!(smal.take().unwrap().read_info().is_err()); })?; let (sinfo, mut smal) = smal.take().unwrap().read_info().expect("Deviation"); assert_eq!(info, sinfo); if info.buffer_size() > 5_000_000 { return Err(()); } let mut ref_data = vec![0; info.buffer_size()]; let mut smal_data = vec![0; info.buffer_size()]; let _rref = reference.next_frame(&mut ref_data); let _rsmal = smal.next_frame(&mut smal_data); assert_eq!(smal_data, ref_data); return Ok(info); }