Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 8 additions & 21 deletions fuzz/fuzz_targets/buf_independent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@
use libfuzzer_sys::fuzz_target;

use std::fmt::Debug;
use std::io::{BufRead, BufReader, Cursor, Seek};
use std::io::{BufRead, BufReader, Cursor};

mod smal_buf {
use std::io::{BufRead, Cursor, Read, Seek};
use std::io::{BufRead, Cursor, Read};

/// A reader that returns at most 1 byte in a single call to `read`.
pub struct SmalBuf {
Expand Down Expand Up @@ -62,22 +62,17 @@ mod smal_buf {
self.inner.consume(amt);
}
}
impl Seek for SmalBuf {
fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result<u64> {
self.inner.seek(pos)
}
}
}

mod intermittent_eofs {

use std::cell::Cell;
use std::io::{BufRead, Read, Seek};
use std::io::{BufRead, Read};
use std::rc::Rc;

/// A reader that returns `std::io::ErrorKind::UnexpectedEof` errors in every other read.
/// EOFs can be temporarily disabled and re-enabled later using the associated `EofController`.
pub struct IntermittentEofs<R: BufRead + Seek> {
pub struct IntermittentEofs<R: BufRead> {
inner: R,

/// Controls whether intermittent EOFs happen at all.
Expand All @@ -88,7 +83,7 @@ mod intermittent_eofs {
eof_soon: bool,
}

impl<R: BufRead + Seek> IntermittentEofs<R> {
impl<R: BufRead> IntermittentEofs<R> {
pub fn new(inner: R) -> Self {
Self {
inner,
Expand All @@ -102,7 +97,7 @@ mod intermittent_eofs {
}
}

impl<R: BufRead + Seek> Read for IntermittentEofs<R> {
impl<R: BufRead> Read for IntermittentEofs<R> {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
if self.controller.are_intermittent_eofs_enabled() && self.eof_soon {
self.eof_soon = false;
Expand All @@ -118,7 +113,7 @@ mod intermittent_eofs {
inner_result
}
}
impl<R: BufRead + Seek> BufRead for IntermittentEofs<R> {
impl<R: BufRead> BufRead for IntermittentEofs<R> {
fn fill_buf(&mut self) -> std::io::Result<&[u8]> {
self.inner.fill_buf()
}
Expand All @@ -127,11 +122,6 @@ mod intermittent_eofs {
self.inner.consume(amt);
}
}
impl<R: BufRead + Seek> Seek for IntermittentEofs<R> {
fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result<u64> {
self.inner.seek(pos)
}
}

pub struct EofController {
are_intermittent_eofs_enabled: Cell<bool>,
Expand Down Expand Up @@ -172,9 +162,6 @@ fuzz_target!(|data: &[u8]| {
let _ = test_data(data);
});

trait BufReadSeek: BufRead + Seek {}
impl<T> BufReadSeek for T where T: BufRead + Seek {}

#[inline(always)]
fn test_data<'a>(data: &'a [u8]) -> Result<(), ()> {
let baseline_reader = Box::new(Cursor::new(data));
Expand All @@ -186,7 +173,7 @@ fn test_data<'a>(data: &'a [u8]) -> Result<(), ()> {

// `Decoder` used to internally wrap the provided reader with a `BufReader`. Now that it has
// been removed, fuzzing would be far too slow if we didn't use a BufReader here.
let data_readers: Vec<BufReader<Box<dyn BufReadSeek>>> = vec![
let data_readers: Vec<BufReader<Box<dyn BufRead>>> = vec![
BufReader::new(baseline_reader),
BufReader::new(byte_by_byte_reader),
BufReader::new(intermittent_eofs_reader),
Expand Down
10 changes: 5 additions & 5 deletions src/decoder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use self::stream::{DecodeOptions, DecodingError, FormatErrorInner};
use self::transform::{create_transform_fn, TransformFn};
use self::unfiltering_buffer::UnfilteringBuffer;

use std::io::{BufRead, Seek};
use std::io::BufRead;
use std::mem;

use crate::adam7::Adam7Info;
Expand Down Expand Up @@ -87,7 +87,7 @@ impl Default for Limits {
}

/// PNG Decoder
pub struct Decoder<R: BufRead + Seek> {
pub struct Decoder<R: BufRead> {
read_decoder: ReadDecoder<R>,
/// Output transformations
transform: Transformations,
Expand Down Expand Up @@ -122,7 +122,7 @@ impl<'data> Row<'data> {
}
}

impl<R: BufRead + Seek> Decoder<R> {
impl<R: BufRead> Decoder<R> {
/// Create a new decoder configuration with default limits.
pub fn new(r: R) -> Decoder<R> {
Decoder::new_with_limits(r, Limits::default())
Expand Down Expand Up @@ -291,7 +291,7 @@ impl<R: BufRead + Seek> Decoder<R> {
/// PNG reader (mostly high-level interface)
///
/// Provides a high level that iterates over lines or whole images.
pub struct Reader<R: BufRead + Seek> {
pub struct Reader<R: BufRead> {
decoder: ReadDecoder<R>,
bpp: BytesPerPixel,
subframe: SubframeInfo,
Expand Down Expand Up @@ -327,7 +327,7 @@ struct SubframeInfo {
consumed_and_flushed: bool,
}

impl<R: BufRead + Seek> Reader<R> {
impl<R: BufRead> Reader<R> {
/// Advances to the start of the next animation frame and
/// returns a reference to the [`FrameControl`] info that describes it.
/// Skips and discards the image data of the previous frame if necessary.
Expand Down
4 changes: 2 additions & 2 deletions src/decoder/read_decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use super::stream::{DecodeOptions, Decoded, DecodingError, FormatErrorInner, Str
use super::zlib::UnfilterBuf;
use super::Limits;

use std::io::{BufRead, ErrorKind, Read, Seek};
use std::io::{BufRead, ErrorKind, Read};

use crate::chunk;
use crate::common::Info;
Expand All @@ -21,7 +21,7 @@ pub(crate) struct ReadDecoder<R: Read> {
decoder: StreamingDecoder,
}

impl<R: BufRead + Seek> ReadDecoder<R> {
impl<R: BufRead> ReadDecoder<R> {
pub fn new(r: R) -> Self {
Self {
reader: r,
Expand Down
17 changes: 1 addition & 16 deletions src/decoder/stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2080,7 +2080,6 @@ mod tests {
use std::fs::File;
use std::io::BufRead;
use std::io::Cursor;
use std::io::Seek;
use std::io::{BufReader, ErrorKind, Read, Write};
use std::rc::Rc;

Expand Down Expand Up @@ -2849,20 +2848,6 @@ mod tests {
assert!(state.current_pos <= state.available_len);
}
}
impl Seek for StreamingInput {
fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result<u64> {
let mut state = self.state.borrow_mut();
state.current_pos = match pos {
std::io::SeekFrom::Start(n) => n as usize,
std::io::SeekFrom::End(n) => (self.full_input.len() as i64 + n) as usize,
std::io::SeekFrom::Current(n) => (state.current_pos as i64 + n) as usize,
} as usize;
Ok(state.current_pos as u64)
}
fn stream_position(&mut self) -> std::io::Result<u64> {
Ok(self.state.borrow().current_pos as u64)
}
}

/// Test resuming/retrying `Reader.next_frame` after `UnexpectedEof`.
#[test]
Expand Down Expand Up @@ -3049,7 +3034,7 @@ mod tests {
Decoder::new(Cursor::new(png)).read_info().unwrap()
}

fn get_fctl_sequence_number(reader: &Reader<impl BufRead + Seek>) -> u32 {
fn get_fctl_sequence_number(reader: &Reader<impl BufRead>) -> u32 {
reader
.info()
.frame_control
Expand Down
2 changes: 0 additions & 2 deletions src/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -674,8 +674,6 @@ impl<W: Write> Writer<W> {
/// the length of `data` can't be parsed as a `u32` though the length of the chunk data should
/// not exceed `i32::MAX` or 2,147,483,647.
pub fn write_chunk(&mut self, name: ChunkType, data: &[u8]) -> Result<()> {
use std::convert::TryFrom;

if u32::try_from(data.len()).map_or(true, |length| length > i32::MAX as u32) {
let kind = FormatErrorKind::WrittenTooMuch(data.len() - i32::MAX as usize);
return Err(EncodingError::Format(kind.into()));
Expand Down
10 changes: 2 additions & 8 deletions tests/partial_decode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ use std::io::Write;

mod pipe {
use std::cell::RefCell;
use std::io::{BufRead, Cursor, Read, Result, Seek, SeekFrom, Write};
use std::io::{BufRead, Cursor, Read, Result, Write};
use std::rc::Rc;

pub fn create() -> (impl BufRead + Seek, impl Write) {
pub fn create() -> (impl BufRead, impl Write) {
let write_end = Pipe {
buf: Rc::new(RefCell::new(Cursor::new(Vec::new()))),
long_lived_fill_buf: Vec::new(),
Expand Down Expand Up @@ -46,12 +46,6 @@ mod pipe {
}
}

impl Seek for Pipe {
fn seek(&mut self, pos: SeekFrom) -> Result<u64> {
self.buf.borrow_mut().seek(pos)
}
}

impl Write for Pipe {
fn write(&mut self, buf: &[u8]) -> Result<usize> {
self.buf.borrow_mut().get_mut().extend_from_slice(buf);
Expand Down
Loading