Enforce maximum size of 400Mp (QOI_PIXELS_MAX)
This commit is contained in:
parent
d0e2b70d3d
commit
4d0d760f92
4 changed files with 14 additions and 3 deletions
|
@ -24,3 +24,5 @@ pub const QOI_PADDING: usize = 4;
|
|||
|
||||
pub const QOI_MAGIC: u32 =
|
||||
(b'q' as u32) << 24 | (b'o' as u32) << 16 | (b'i' as u32) << 8 | (b'f' as u32);
|
||||
|
||||
pub const QOI_PIXELS_MAX: usize = 400_000_000;
|
||||
|
|
|
@ -3,7 +3,7 @@ use std::slice;
|
|||
use crate::colorspace::ColorSpace;
|
||||
use crate::consts::{
|
||||
QOI_COLOR, QOI_DIFF_16, QOI_DIFF_24, QOI_DIFF_8, QOI_HEADER_SIZE, QOI_INDEX, QOI_PADDING,
|
||||
QOI_RUN_16, QOI_RUN_8,
|
||||
QOI_PIXELS_MAX, QOI_RUN_16, QOI_RUN_8,
|
||||
};
|
||||
use crate::error::{Error, Result};
|
||||
use crate::header::Header;
|
||||
|
@ -137,6 +137,8 @@ where
|
|||
let n_pixels = (width as usize) * (height as usize);
|
||||
if unlikely(data.is_empty()) {
|
||||
return Err(Error::EmptyImage { width, height });
|
||||
} else if unlikely(n_pixels > QOI_PIXELS_MAX) {
|
||||
return Err(Error::ImageTooLarge { width, height });
|
||||
} else if unlikely(n_pixels * CHANNELS != data.len()) {
|
||||
return Err(Error::BadEncodingDataSize { size: data.len(), expected: n_pixels * CHANNELS });
|
||||
}
|
||||
|
|
|
@ -2,12 +2,13 @@ use std::error::Error as StdError;
|
|||
use std::fmt::{self, Display};
|
||||
use std::result::Result as StdResult;
|
||||
|
||||
use crate::consts::QOI_MAGIC;
|
||||
use crate::consts::{QOI_MAGIC, QOI_PIXELS_MAX};
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum Error {
|
||||
InvalidChannels { channels: u8 },
|
||||
EmptyImage { width: u32, height: u32 },
|
||||
ImageTooLarge { width: u32, height: u32 },
|
||||
BadEncodingDataSize { size: usize, expected: usize },
|
||||
InputBufferTooSmall { size: usize, required: usize },
|
||||
OutputBufferTooSmall { size: usize, required: usize },
|
||||
|
@ -27,6 +28,10 @@ impl Display for Error {
|
|||
Self::EmptyImage { width, height } => {
|
||||
write!(f, "image contains no pixels: {}x{}", width, height)
|
||||
}
|
||||
Self::ImageTooLarge { width, height } => {
|
||||
let mp = QOI_PIXELS_MAX / 1_000_000;
|
||||
write!(f, "image is too large: {}x{} (max={}Mp)", width, height, mp)
|
||||
}
|
||||
Self::BadEncodingDataSize { size, expected } => {
|
||||
write!(f, "bad data size when encoding: {} (expected: {})", size, expected)
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::colorspace::ColorSpace;
|
||||
use crate::consts::{QOI_HEADER_SIZE, QOI_MAGIC};
|
||||
use crate::consts::{QOI_HEADER_SIZE, QOI_MAGIC, QOI_PIXELS_MAX};
|
||||
use crate::error::{Error, Result};
|
||||
use crate::utils::unlikely;
|
||||
|
||||
|
@ -90,6 +90,8 @@ impl Header {
|
|||
return Err(Error::InvalidMagic { magic: self.magic });
|
||||
} else if unlikely(self.height == 0 || self.width == 0) {
|
||||
return Err(Error::EmptyImage { width: self.width, height: self.height });
|
||||
} else if unlikely((self.height as usize) * (self.width as usize) > QOI_PIXELS_MAX) {
|
||||
return Err(Error::ImageTooLarge { width: self.width, height: self.height });
|
||||
} else if unlikely(self.channels < 3 || self.channels > 4) {
|
||||
return Err(Error::InvalidChannels { channels: self.channels });
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue