diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..cc267bc --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,39 @@ +name: CI + +on: + pull_request: + branches: + - master + push: + branches: + - master + +env: + CARGO_TERM_COLOR: always + RUST_BACKTRACE: 1 + RUSTFLAGS: -Dwarnings + +jobs: + check-test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: "Install minimal stable with clippy" + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + components: clippy + + - name: "Clippy" + uses: actions-rs/cargo@v1 + with: + command: clippy + args: --all-targets + + - name: "Test" + uses: actions-rs/cargo@v1 + with: + command: test + args: --tests --benches --examples diff --git a/src/lib.rs b/src/lib.rs index 343ae90..789d13d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -150,12 +150,8 @@ where P: AsRef, { let file = File::open(path)?; - let mut reader = BufReader::new(file); - - let mut header = [0; 12]; - reader.read_exact(&mut header)?; - - dispatch_header(&mut reader, &header) + let reader = BufReader::new(file); + reader_size(reader) } /// Get the image size from a block of raw data. @@ -186,8 +182,47 @@ where /// /// [`ImageError`]: enum.ImageError.html pub fn blob_size(data: &[u8]) -> ImageResult { - let mut reader = Cursor::new(data); + let reader = Cursor::new(data); + reader_size(reader) +} +/// Get the image size from a reader +/// +/// # Arguments +/// * `reader` - A reader for the data +/// +/// # Error +/// +/// This method will return an [`ImageError`] under the following conditions: +/// +/// * The header isn't recognized as a supported image format +/// * The data isn't long enough to find the size for the given format +/// +/// # Examples +/// +/// ``` +/// use std::io::Cursor; +/// use imagesize::reader_size; +/// +/// // PNG Header with size 123x321 +/// let reader = Cursor::new([ +/// 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, +/// 0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44, 0x52, +/// 0x00, 0x00, 0x00, 0x7B, 0x00, 0x00, 0x01, 0x41, +/// 0x08, 0x06, 0x00, 0x00, 0x00, 0x9A, 0x38, 0xC4 +/// ]); +/// +/// match reader_size(reader) { +/// Ok(dim) => { +/// assert_eq!(dim.width, 123); +/// assert_eq!(dim.height, 321); +/// } +/// Err(why) => println!("Error getting reader size: {:?}", why) +/// } +/// ``` +/// +/// [`ImageError`]: enum.ImageError.html +pub fn reader_size(mut reader: R) -> ImageResult { let mut header = [0; 12]; reader.read_exact(&mut header)?; diff --git a/tests/fuzz.rs b/tests/fuzz.rs index f771052..fe6049a 100644 --- a/tests/fuzz.rs +++ b/tests/fuzz.rs @@ -26,7 +26,7 @@ fn get_file_as_byte_vec(filename: PathBuf) -> Vec { let mut f = File::open(&filename).expect("no file found"); let metadata = metadata(&filename).expect("unable to read metadata"); let mut buffer = vec![0; metadata.len() as usize]; - f.read(&mut buffer).expect("buffer overflow"); + f.read_exact(&mut buffer).expect("buffer overflow"); buffer } diff --git a/tests/reader.rs b/tests/reader.rs new file mode 100644 index 0000000..0a1e236 --- /dev/null +++ b/tests/reader.rs @@ -0,0 +1,27 @@ +#[cfg(test)] +use imagesize::reader_size; +use std::io::Cursor; + +#[test] +fn reader_test() { + // PNG Header with size 123x321 + let reader = Cursor::new([ + 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, + 0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44, 0x52, + 0x00, 0x00, 0x00, 0x7B, 0x00, 0x00, 0x01, 0x41, + 0x08, 0x06, 0x00, 0x00, 0x00, 0x9A, 0x38, 0xC4 + ]); + let dim = reader_size(reader).unwrap(); + assert_eq!(dim.width, 123); + assert_eq!(dim.height, 321); +} + +#[test] +fn reader_test_fail() { + // only header part of webp + let webp_reader = Cursor::new([ + 0x52, 0x49, 0x46, 0x46, 0xD8, 0xA1, 0x00, 0x00, + 0x57, 0x45, 0x42, 0x50, 0x56, 0x50, 0x38, 0x58 + ]); + assert!(reader_size(webp_reader).is_err()); +}