use std::io::Cursor;
use image::{
io::Limits, load_from_memory_with_format, ImageDecoder, ImageFormat, ImageOutputFormat,
RgbImage,
};
const WIDTH: u32 = 256;
const HEIGHT: u32 = 256;
fn test_image(format: ImageOutputFormat) -> Vec<u8> {
let image = RgbImage::new(WIDTH, HEIGHT);
let mut bytes: Vec<u8> = Vec::new();
image
.write_to(&mut Cursor::new(&mut bytes), format)
.unwrap();
bytes
}
fn width_height_limits() -> Limits {
let mut limits = Limits::no_limits();
limits.max_image_width = Some(WIDTH / 2);
limits.max_image_height = Some(HEIGHT / 2);
limits
}
fn allocation_limits() -> Limits {
let mut limits = Limits::no_limits();
limits.max_alloc = Some(((WIDTH / 2) * (HEIGHT / 2) * 3).into()); limits
}
fn permissive_limits() -> Limits {
let mut limits = Limits::no_limits();
limits.max_image_width = Some(WIDTH);
limits.max_image_height = Some(HEIGHT);
limits.max_alloc = Some((WIDTH * HEIGHT * 5).into()); limits
}
fn load_through_reader(
input: &[u8],
format: ImageFormat,
limits: Limits,
) -> Result<image::DynamicImage, image::ImageError> {
let mut reader = image::io::Reader::new(Cursor::new(input));
reader.set_format(format);
reader.limits(limits);
reader.decode()
}
#[test]
#[cfg(feature = "gif")]
fn gif() {
use image::codecs::gif::GifDecoder;
let image = test_image(ImageOutputFormat::Gif);
assert!(load_from_memory_with_format(&image, ImageFormat::Gif).is_ok());
assert!(load_through_reader(&image, ImageFormat::Gif, permissive_limits()).is_ok());
assert!(load_through_reader(&image, ImageFormat::Gif, width_height_limits()).is_err());
assert!(load_through_reader(&image, ImageFormat::Gif, allocation_limits()).is_err());
let mut decoder = GifDecoder::new(Cursor::new(&image)).unwrap();
assert!(decoder.set_limits(width_height_limits()).is_err());
#[allow(deprecated)]
{
assert!(GifDecoder::with_limits(Cursor::new(&image), width_height_limits()).is_err());
}
}
#[test]
#[cfg(feature = "png")]
fn png() {
use image::codecs::png::PngDecoder;
let image = test_image(ImageOutputFormat::Png);
assert!(load_from_memory_with_format(&image, ImageFormat::Png).is_ok());
assert!(load_through_reader(&image, ImageFormat::Png, permissive_limits()).is_ok());
assert!(load_through_reader(&image, ImageFormat::Png, width_height_limits()).is_err());
assert!(load_through_reader(&image, ImageFormat::Png, allocation_limits()).is_err());
let mut decoder = PngDecoder::new(Cursor::new(&image)).unwrap();
assert!(decoder.set_limits(width_height_limits()).is_err());
assert!(PngDecoder::with_limits(Cursor::new(&image), width_height_limits()).is_err());
}
#[test]
#[cfg(feature = "jpeg")]
fn jpeg() {
use image::codecs::jpeg::JpegDecoder;
let image = test_image(ImageOutputFormat::Jpeg(80));
assert!(load_from_memory_with_format(&image, ImageFormat::Jpeg).is_ok());
assert!(load_through_reader(&image, ImageFormat::Jpeg, permissive_limits()).is_ok());
assert!(load_through_reader(&image, ImageFormat::Jpeg, width_height_limits()).is_err());
assert!(load_through_reader(&image, ImageFormat::Jpeg, allocation_limits()).is_err());
let mut decoder = JpegDecoder::new(Cursor::new(&image)).unwrap();
assert!(decoder.set_limits(width_height_limits()).is_err());
}
#[test]
#[cfg(feature = "webp")]
fn webp() {
use image::codecs::webp::WebPDecoder;
let image = test_image(ImageOutputFormat::WebP);
assert!(load_from_memory_with_format(&image, ImageFormat::WebP).is_ok());
assert!(load_through_reader(&image, ImageFormat::WebP, permissive_limits()).is_ok());
assert!(load_through_reader(&image, ImageFormat::WebP, width_height_limits()).is_err());
assert!(load_through_reader(&image, ImageFormat::WebP, allocation_limits()).is_err());
let mut decoder = WebPDecoder::new(Cursor::new(&image)).unwrap();
assert!(decoder.set_limits(width_height_limits()).is_err());
}
#[test]
#[cfg(feature = "tiff")]
fn tiff() {
use image::codecs::tiff::TiffDecoder;
let image = test_image(ImageOutputFormat::Tiff);
assert!(load_from_memory_with_format(&image, ImageFormat::Tiff).is_ok());
let mut tiff_permissive_limits = permissive_limits();
tiff_permissive_limits.max_alloc = Some((WIDTH * HEIGHT * 8).into()); load_through_reader(&image, ImageFormat::Tiff, tiff_permissive_limits).unwrap();
assert!(load_through_reader(&image, ImageFormat::Tiff, width_height_limits()).is_err());
assert!(load_through_reader(&image, ImageFormat::Tiff, allocation_limits()).is_err());
let mut decoder = TiffDecoder::new(Cursor::new(&image)).unwrap();
assert!(decoder.set_limits(width_height_limits()).is_err());
}
#[test]
#[cfg(all(feature = "avif", feature = "avif-decoder"))]
fn avif() {
use image::codecs::avif::AvifDecoder;
let image = test_image(ImageOutputFormat::Avif);
assert!(load_from_memory_with_format(&image, ImageFormat::Avif).is_ok());
assert!(load_through_reader(&image, ImageFormat::Avif, permissive_limits()).is_ok());
assert!(load_through_reader(&image, ImageFormat::Avif, width_height_limits()).is_err());
assert!(load_through_reader(&image, ImageFormat::Avif, allocation_limits()).is_err());
let mut decoder = AvifDecoder::new(Cursor::new(&image)).unwrap();
assert!(decoder.set_limits(width_height_limits()).is_err());
}
#[test]
#[cfg(feature = "bmp")]
fn bmp() {
use image::codecs::bmp::BmpDecoder;
let image = test_image(ImageOutputFormat::Bmp);
assert!(load_from_memory_with_format(&image, ImageFormat::Bmp).is_ok());
assert!(load_through_reader(&image, ImageFormat::Bmp, permissive_limits()).is_ok());
assert!(load_through_reader(&image, ImageFormat::Bmp, width_height_limits()).is_err());
assert!(load_through_reader(&image, ImageFormat::Bmp, allocation_limits()).is_err());
let mut decoder = BmpDecoder::new(Cursor::new(&image)).unwrap();
assert!(decoder.set_limits(width_height_limits()).is_err());
}