/src/image/fuzz/fuzzers/fuzzer_script_exr.rs
Line | Count | Source (jump to first uncovered line) |
1 | | #![no_main] |
2 | | #[macro_use] |
3 | | extern crate libfuzzer_sys; |
4 | | extern crate image; |
5 | | |
6 | | use image::codecs::openexr::*; |
7 | | use image::Limits; |
8 | | use image::ExtendedColorType; |
9 | | use image::ImageDecoder; |
10 | | use image::ImageEncoder; |
11 | | use image::ImageResult; |
12 | | use std::io::{BufRead, Cursor, Seek, Write}; |
13 | | |
14 | | // "just dont panic" |
15 | 0 | fn roundtrip(bytes: &[u8]) -> ImageResult<()> { |
16 | | /// Read the file from the specified path into an `Rgba32FImage`. |
17 | | // TODO this method should probably already exist in the main image crate |
18 | 0 | fn read_as_rgba_byte_image(read: impl BufRead + Seek) -> ImageResult<(u32, u32, Vec<u8>)> { |
19 | 0 | let mut decoder = OpenExrDecoder::with_alpha_preference(read, Some(true))?; |
20 | 0 | match usize::try_from(decoder.total_bytes()) { |
21 | 0 | Ok(decoded_size) if decoded_size <= 256 * 1024 * 1024 => { |
22 | 0 | decoder.set_limits(Limits::default())?; |
23 | 0 | let (width, height) = decoder.dimensions(); |
24 | 0 | let mut buffer = vec![0; decoded_size]; |
25 | 0 | decoder.read_image(buffer.as_mut_slice())?; |
26 | 0 | Ok((width, height, buffer)) |
27 | | } |
28 | 0 | _ => Err(image::ImageError::Limits( |
29 | 0 | image::error::LimitError::from_kind( |
30 | 0 | image::error::LimitErrorKind::InsufficientMemory, |
31 | 0 | ), |
32 | 0 | )), |
33 | | } |
34 | 0 | } Unexecuted instantiation: fuzzer_script_exr::roundtrip::read_as_rgba_byte_image::<std::io::cursor::Cursor<alloc::vec::Vec<u8>>> Unexecuted instantiation: fuzzer_script_exr::roundtrip::read_as_rgba_byte_image::<std::io::cursor::Cursor<&[u8]>> |
35 | | |
36 | | /// Write an `Rgba32FImage`. |
37 | | /// Assumes the writer is buffered. In most cases, |
38 | | /// you should wrap your writer in a `BufWriter` for best performance. |
39 | | // TODO this method should probably already exist in the main image crate |
40 | 0 | fn write_rgba_image( |
41 | 0 | write: impl Write + Seek, |
42 | 0 | (width, height, data): &(u32, u32, Vec<u8>), |
43 | 0 | ) -> ImageResult<()> { |
44 | 0 | OpenExrEncoder::new(write).write_image( |
45 | 0 | data.as_slice(), |
46 | 0 | *width, |
47 | 0 | *height, |
48 | 0 | ExtendedColorType::Rgba32F, |
49 | 0 | ) |
50 | 0 | } |
51 | | |
52 | 0 | let decoded_image = read_as_rgba_byte_image(Cursor::new(bytes))?; |
53 | | |
54 | 0 | let mut bytes = Vec::with_capacity(bytes.len() + 20); |
55 | 0 | write_rgba_image(Cursor::new(&mut bytes), &decoded_image)?; |
56 | | |
57 | 0 | let redecoded_image = read_as_rgba_byte_image(Cursor::new(bytes))?; |
58 | | |
59 | | // if both images are valid, assert read/write consistency |
60 | 0 | assert_eq!( |
61 | | decoded_image, redecoded_image, |
62 | 0 | "image was valid but was not reproducible" |
63 | | ); |
64 | 0 | Ok(()) |
65 | 0 | } |
66 | | |
67 | | fuzz_target!(|data: &[u8]| { |
68 | | let _img = roundtrip(data); // fixme not optimized away? |
69 | | }); |