#[derive(Clone, Copy, Debug)]
pub struct ParseLimits {
pub max_dimension: u32,
pub max_pixels: u64,
pub max_box_size: u64,
pub max_item_size: u64,
pub max_hvcc_size: usize,
pub max_exif_size: usize,
pub max_items: usize,
pub max_extents_per_item: usize,
pub max_tiles: usize,
}
impl ParseLimits {
pub const DEFAULT_MAX_DIMENSION: u32 = 16_384;
pub const DEFAULT_MAX_PIXELS: u64 = 64 * 1024 * 1024;
pub const DEFAULT_MAX_BOX_SIZE: u64 = 256 * 1024 * 1024;
pub const DEFAULT_MAX_ITEM_SIZE: u64 = 256 * 1024 * 1024;
pub const DEFAULT_MAX_HVCC_SIZE: usize = 64 * 1024;
pub const DEFAULT_MAX_EXIF_SIZE: usize = 1024 * 1024;
pub const DEFAULT_MAX_ITEMS: usize = 4096;
pub const DEFAULT_MAX_EXTENTS_PER_ITEM: usize = 64;
pub const DEFAULT_MAX_TILES: usize = 16_384;
pub const fn new() -> Self {
ParseLimits {
max_dimension: Self::DEFAULT_MAX_DIMENSION,
max_pixels: Self::DEFAULT_MAX_PIXELS,
max_box_size: Self::DEFAULT_MAX_BOX_SIZE,
max_item_size: Self::DEFAULT_MAX_ITEM_SIZE,
max_hvcc_size: Self::DEFAULT_MAX_HVCC_SIZE,
max_exif_size: Self::DEFAULT_MAX_EXIF_SIZE,
max_items: Self::DEFAULT_MAX_ITEMS,
max_extents_per_item: Self::DEFAULT_MAX_EXTENTS_PER_ITEM,
max_tiles: Self::DEFAULT_MAX_TILES,
}
}
pub(crate) fn check_image(&self, w: u32, h: u32) -> Result<(), crate::error::DecodeError> {
use crate::error::DecodeError;
if w == 0 || h == 0 {
return Err(DecodeError::BadDimensions { w, h });
}
if w > self.max_dimension {
return Err(DecodeError::LimitExceeded {
what: "image width",
value: w as u64,
limit: self.max_dimension as u64,
});
}
if h > self.max_dimension {
return Err(DecodeError::LimitExceeded {
what: "image height",
value: h as u64,
limit: self.max_dimension as u64,
});
}
let px = w as u64 * h as u64;
if px > self.max_pixels {
return Err(DecodeError::LimitExceeded {
what: "image pixels",
value: px,
limit: self.max_pixels,
});
}
Ok(())
}
}
impl Default for ParseLimits {
fn default() -> Self {
ParseLimits::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn defaults_accept_reasonable_and_reject_huge() {
let l = ParseLimits::default();
assert!(l.check_image(4032, 3024).is_ok()); assert!(l.check_image(0, 3024).is_err()); assert!(l.check_image(17_000, 10).is_err()); assert!(l.check_image(16_000, 16_000).is_err()); }
#[test]
fn custom_limits_are_honoured() {
let l = ParseLimits {
max_dimension: 1000,
max_pixels: 500_000,
..ParseLimits::default()
};
assert!(l.check_image(800, 600).is_ok());
assert!(l.check_image(1001, 1).is_err());
assert!(l.check_image(900, 900).is_err()); }
}