Handle files with invalid filters (#410)
The bad filter case is reachable, and can happen when the PNG file is corrupted.
This commit is contained in:
parent
286aaffa31
commit
ea75f6ccc1
2 changed files with 15 additions and 6 deletions
|
|
@ -1,3 +1,5 @@
|
|||
use crate::error::PngError;
|
||||
|
||||
pub fn filter_line(filter: u8, bpp: usize, data: &[u8], last_line: &[u8], buf: &mut Vec<u8>) {
|
||||
assert!(data.len() >= bpp);
|
||||
assert!(last_line.is_empty() || data.len() == last_line.len());
|
||||
|
|
@ -65,7 +67,13 @@ pub fn filter_line(filter: u8, bpp: usize, data: &[u8], last_line: &[u8], buf: &
|
|||
}
|
||||
}
|
||||
|
||||
pub fn unfilter_line(filter: u8, bpp: usize, data: &[u8], last_line: &[u8], buf: &mut Vec<u8>) {
|
||||
pub fn unfilter_line(
|
||||
filter: u8,
|
||||
bpp: usize,
|
||||
data: &[u8],
|
||||
last_line: &[u8],
|
||||
buf: &mut Vec<u8>,
|
||||
) -> Result<(), PngError> {
|
||||
buf.clear();
|
||||
buf.reserve(data.len());
|
||||
assert!(data.len() >= bpp);
|
||||
|
|
@ -114,8 +122,9 @@ pub fn unfilter_line(filter: u8, bpp: usize, data: &[u8], last_line: &[u8], buf:
|
|||
);
|
||||
}
|
||||
}
|
||||
_ => unreachable!(),
|
||||
_ => return Err(PngError::InvalidData),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn paeth_predictor(a: u8, b: u8, c: u8) -> u8 {
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ impl PngData {
|
|||
transparency_pixel,
|
||||
aux_headers,
|
||||
};
|
||||
raw.data = raw.unfilter_image();
|
||||
raw.data = raw.unfilter_image()?;
|
||||
// Return the PngData
|
||||
Ok(Self {
|
||||
idat_data: idat_headers,
|
||||
|
|
@ -281,7 +281,7 @@ impl PngImage {
|
|||
}
|
||||
|
||||
/// Reverse all filters applied on the image, returning an unfiltered IDAT bytestream
|
||||
fn unfilter_image(&self) -> Vec<u8> {
|
||||
fn unfilter_image(&self) -> Result<Vec<u8>, PngError> {
|
||||
let mut unfiltered = Vec::with_capacity(self.data.len());
|
||||
let bpp = ((self.ihdr.bit_depth.as_u8() * self.channels_per_pixel() + 7) / 8) as usize;
|
||||
let mut last_line: Vec<u8> = Vec::new();
|
||||
|
|
@ -293,13 +293,13 @@ impl PngImage {
|
|||
last_pass = line.pass;
|
||||
}
|
||||
last_line.resize(line.data.len(), 0);
|
||||
unfilter_line(line.filter, bpp, line.data, &last_line, &mut unfiltered_buf);
|
||||
unfilter_line(line.filter, bpp, line.data, &last_line, &mut unfiltered_buf)?;
|
||||
unfiltered.push(0);
|
||||
unfiltered.extend_from_slice(&unfiltered_buf);
|
||||
std::mem::swap(&mut last_line, &mut unfiltered_buf);
|
||||
unfiltered_buf.clear();
|
||||
}
|
||||
unfiltered
|
||||
Ok(unfiltered)
|
||||
}
|
||||
|
||||
/// Apply the specified filter type to all rows in the image
|
||||
|
|
|
|||
Loading…
Reference in a new issue