Skip to content

Commit

Permalink
Add PngDecoder::with_limits
Browse files Browse the repository at this point in the history
  • Loading branch information
fintelia committed Oct 25, 2022
1 parent 14eae6d commit 42ee595
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 8 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Expand Up @@ -36,7 +36,7 @@ num-rational = { version = "0.4", default-features = false }
num-traits = "0.2.0"
gif = { version = "0.11.1", optional = true }
jpeg = { package = "jpeg-decoder", version = "0.2.1", default-features = false, optional = true }
png = { version = "0.17.0", optional = true }
png = { version = "0.17.6", optional = true }
scoped_threadpool = { version = "0.1", optional = true }
tiff = { version = "0.7.1", optional = true }
ravif = { version = "0.8.0", optional = true }
Expand Down
18 changes: 14 additions & 4 deletions src/codecs/png.rs
Expand Up @@ -20,6 +20,7 @@ use crate::error::{
ParameterError, ParameterErrorKind, UnsupportedError, UnsupportedErrorKind,
};
use crate::image::{AnimationDecoder, ImageDecoder, ImageEncoder, ImageFormat};
use crate::io::Limits;
use crate::{DynamicImage, GenericImage, ImageBuffer, Luma, LumaA, Rgb, Rgba, RgbaImage};

// http://www.w3.org/TR/PNG-Structure.html
Expand Down Expand Up @@ -117,10 +118,19 @@ pub struct PngDecoder<R: Read> {
impl<R: Read> PngDecoder<R> {
/// Creates a new decoder that decodes from the stream ```r```
pub fn new(r: R) -> ImageResult<PngDecoder<R>> {
let limits = png::Limits {
bytes: usize::max_value(),
};
let mut decoder = png::Decoder::new_with_limits(r, limits);
Self::with_limits(r, Limits::default())
}

/// Creates a new decoder that decodes from the stream ```r``` with the given limits.
pub fn with_limits(r: R, limits: Limits) -> ImageResult<PngDecoder<R>> {
limits.check_support(&crate::io::LimitSupport::default())?;

let max_bytes = usize::try_from(limits.max_alloc.unwrap_or(u64::MAX)).unwrap_or(usize::MAX);
let mut decoder = png::Decoder::new_with_limits(r, png::Limits { bytes: max_bytes });

let info = decoder.read_header_info().map_err(ImageError::from_png)?;
limits.check_dimensions(info.width, info.height)?;

// By default the PNG decoder will scale 16 bpc to 8 bpc, so custom
// transformations must be set. EXPAND preserves the default behavior
// expanding bpc < 8 to 8 bpc.
Expand Down
7 changes: 4 additions & 3 deletions src/io/free_functions.rs
Expand Up @@ -45,6 +45,7 @@ pub(crate) trait DecoderVisitor {
pub(crate) fn load_decoder<R: BufRead + Seek, V: DecoderVisitor>(
r: R,
format: ImageFormat,
limits: super::Limits,
visitor: V,
) -> ImageResult<V::Result> {
#[allow(unreachable_patterns)]
Expand All @@ -53,7 +54,7 @@ pub(crate) fn load_decoder<R: BufRead + Seek, V: DecoderVisitor>(
#[cfg(feature = "avif-decoder")]
image::ImageFormat::Avif => visitor.visit_decoder(avif::AvifDecoder::new(r)?),
#[cfg(feature = "png")]
image::ImageFormat::Png => visitor.visit_decoder(png::PngDecoder::new(r)?),
image::ImageFormat::Png => visitor.visit_decoder(png::PngDecoder::with_limits(r, limits)?),
#[cfg(feature = "gif")]
image::ImageFormat::Gif => visitor.visit_decoder(gif::GifDecoder::new(r)?),
#[cfg(feature = "jpeg")]
Expand Down Expand Up @@ -107,7 +108,7 @@ pub(crate) fn load_inner<R: BufRead + Seek>(
}
}

load_decoder(r, format, LoadVisitor(limits))
load_decoder(r, format, limits.clone(), LoadVisitor(limits))
}

pub(crate) fn image_dimensions_impl(path: &Path) -> ImageResult<(u32, u32)> {
Expand All @@ -131,7 +132,7 @@ pub(crate) fn image_dimensions_with_format_impl<R: BufRead + Seek>(
}
}

load_decoder(buffered_read, format, DimVisitor)
load_decoder(buffered_read, format, super::Limits::default(), DimVisitor)
}

#[allow(unused_variables)]
Expand Down

0 comments on commit 42ee595

Please sign in to comment.