summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2023-09-20 23:38:34 -0400
committerpommicket <pommicket@gmail.com>2023-09-20 23:38:34 -0400
commit521a88b66f0bd76c52fef0d84776478c0b0664d9 (patch)
tree0df450d897f6e3ab422f83b8a0ef54d769d023cf /src
parentbac500bc1289d9bf2c61173bd170bc721406087a (diff)
- add overflow check for chunk length.HEAD0.1.1trunk
this could have resulted in debug-only panics for maliciously crafted images. - add “impossible compressed size” check which slightly mitigates the problem of a malicious image causing you to allocate a shitton of memory.
Diffstat (limited to 'src')
-rw-r--r--src/lib.rs14
1 files changed, 14 insertions, 0 deletions
diff --git a/src/lib.rs b/src/lib.rs
index b17c413..9d61021 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -53,6 +53,10 @@ pub enum Error {
NoIdat,
/// Adler-32 checksum doesn't check out (invalid PNG file)
BadAdlerChecksum,
+ /// e.g. chunk is larger than 2GB, chunk goes past end of file (invalid PNG)
+ BadChunkSize,
+ /// compressed data cannot possibly be expanded to the full image because it's too small (invalid PNG)
+ CompressedSizeTooSmall,
}
#[cold]
@@ -86,6 +90,8 @@ impl Display for Error {
Self::NoIdat => write!(f, "missing IDAT chunk"),
Self::BadNlen => write!(f, "LEN doesn't match NLEN"),
Self::BadAdlerChecksum => write!(f, "bad adler-32 checksum"),
+ Self::BadChunkSize => write!(f, "bad chunk size"),
+ Self::CompressedSizeTooSmall => write!(f, "compressed data too small"),
}
}
}
@@ -857,6 +863,11 @@ pub fn decode_png_header(bytes: &[u8]) -> Result<ImageHeader> {
color_type,
length: 8 + ihdr_len,
};
+ // in the best-case scenario, each bit can decompress to 258 bytes
+ // (see DEFLATE RFC especially §3.2.5).
+ if hdr.decompressed_size() / (8 * 258) > bytes.len() {
+ return Err(Error::CompressedSizeTooSmall);
+ }
Ok(hdr)
}
@@ -1215,6 +1226,9 @@ fn read_non_idat_chunks(
])
.try_into()
.map_err(|_| Error::TooLargeForUsize)?;
+ if chunk_len > 0x7FFF_FFFF || chunk_len > reader.0.len() {
+ return Err(Error::BadChunkSize);
+ }
let chunk_type = [
chunk_header[4],
chunk_header[5],