aboutsummaryrefslogtreecommitdiff
path: root/projects/image-png/buf_independent.rs
diff options
context:
space:
mode:
Diffstat (limited to 'projects/image-png/buf_independent.rs')
-rw-r--r--projects/image-png/buf_independent.rs74
1 files changed, 74 insertions, 0 deletions
diff --git a/projects/image-png/buf_independent.rs b/projects/image-png/buf_independent.rs
new file mode 100644
index 000000000..f4a1f312c
--- /dev/null
+++ b/projects/image-png/buf_independent.rs
@@ -0,0 +1,74 @@
+#![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<R: BufRead> {
+ inner: R,
+ cap: usize,
+}
+
+impl<R: BufRead> SmalBuf<R> {
+ fn new(inner: R, cap: usize) -> Self {
+ SmalBuf { inner, cap }
+ }
+}
+
+impl<R: BufRead> Read for SmalBuf<R> {
+ fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
+ let len = buf.len().min(self.cap);
+ self.inner.read(&mut buf[..len])
+ }
+}
+
+impl<R: BufRead> BufRead for SmalBuf<R> {
+ 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<R: BufRead, S: BufRead>(reference: png::Decoder<R>, smal: png::Decoder<S>)
+ -> std::result::Result<png::OutputInfo, ()>
+{
+ 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);
+}