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