1 #![no_main]
2 extern crate libfuzzer_sys;
3 use libfuzzer_sys::fuzz_target;
4 extern crate png;
5 
6 use std::io::{BufRead, Read, Result};
7 
8 /// A reader that reads at most `n` bytes.
9 struct SmalBuf<R: BufRead> {
10     inner: R,
11     cap: usize,
12 }
13 
14 impl<R: BufRead> SmalBuf<R> {
new(inner: R, cap: usize) -> Self15     fn new(inner: R, cap: usize) -> Self {
16         SmalBuf { inner, cap }
17     }
18 }
19 
20 impl<R: BufRead> Read for SmalBuf<R> {
read(&mut self, buf: &mut [u8]) -> Result<usize>21     fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
22         let len = buf.len().min(self.cap);
23         self.inner.read(&mut buf[..len])
24     }
25 }
26 
27 impl<R: BufRead> BufRead for SmalBuf<R> {
fill_buf(&mut self) -> Result<&[u8]>28     fn fill_buf(&mut self) -> Result<&[u8]> {
29         let buf = self.inner.fill_buf()?;
30         let len = buf.len().min(self.cap);
31         Ok(&buf[..len])
32     }
33 
consume(&mut self, amt: usize)34     fn consume(&mut self, amt: usize) {
35         assert!(amt <= self.cap);
36         self.inner.consume(amt)
37     }
38 }
39 
40 fuzz_target!(|data: &[u8]| {
41     // Small limits, we don't need them hopefully.
42     let limits = png::Limits { bytes: 1 << 16 };
43 
44     let reference = png::Decoder::new_with_limits(data, limits);
45     let smal = png::Decoder::new_with_limits(SmalBuf::new(data, 1), limits);
46 
47     let _ = png_compare(reference, smal);
48 });
49 
50 #[inline(always)]
png_compare<R: BufRead, S: BufRead>(reference: png::Decoder<R>, smal: png::Decoder<S>) -> std::result::Result<png::OutputInfo, ()>51 fn png_compare<R: BufRead, S: BufRead>(reference: png::Decoder<R>, smal: png::Decoder<S>)
52     -> std::result::Result<png::OutputInfo, ()>
53 {
54     let mut smal = Some(smal);
55     let (info, mut reference) = reference.read_info().map_err(|_| {
56         assert!(smal.take().unwrap().read_info().is_err());
57     })?;
58 
59     let (sinfo, mut smal) = smal.take().unwrap().read_info().expect("Deviation");
60     assert_eq!(info, sinfo);
61 
62     if info.buffer_size() > 5_000_000 {
63         return Err(());
64     }
65 
66     let mut ref_data = vec![0; info.buffer_size()];
67     let mut smal_data = vec![0; info.buffer_size()];
68 
69     let _rref = reference.next_frame(&mut ref_data);
70     let _rsmal = smal.next_frame(&mut smal_data);
71 
72     assert_eq!(smal_data, ref_data);
73     return Ok(info);
74 }
75