Skip to content

Commit

Permalink
Merge pull request #161 from kornelski/depanic
Browse files Browse the repository at this point in the history
Avoid panic on truncated palette
  • Loading branch information
kornelski authored Jan 10, 2024
2 parents ff242b0 + fee622d commit c33079b
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 16 deletions.
4 changes: 2 additions & 2 deletions src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,10 +239,10 @@ impl Frame<'static> {
let mut colors_vec: Vec<(u8, u8, u8, u8)> = colors.into_iter().collect();
colors_vec.sort_unstable();
let palette = colors_vec.iter().flat_map(|&(r, g, b, _a)| [r, g, b]).collect();
let colors_lookup: HashMap<(u8, u8, u8, u8), u8> = colors_vec.into_iter().zip(0..=255).collect();
let colors_lookup: HashMap<(u8, u8, u8, u8), u8> = colors_vec.into_iter().zip(0..=255).collect();

let index_of = | pixel: &[u8] |
*colors_lookup.get(&(pixel[0], pixel[1], pixel[2], pixel[3])).unwrap();
colors_lookup.get(&(pixel[0], pixel[1], pixel[2], pixel[3])).copied().unwrap_or(0);

return Frame {
width,
Expand Down
35 changes: 21 additions & 14 deletions src/reader/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -403,8 +403,9 @@ impl StreamingDecoder {
self.current.as_mut().unwrap()
}

#[inline(always)]
/// Current frame info as a ref.
#[inline(always)]
#[track_caller]
pub fn current_frame<'a>(&'a self) -> &'a Frame<'static> {
self.current.as_ref().unwrap()
}
Expand Down Expand Up @@ -486,9 +487,9 @@ impl StreamingDecoder {
goto!(Byte(ByteValue::GlobalFlags))
},
(Delay, delay) => {
self.current_frame_mut().delay = delay;
self.ext.data.push(value as u8);
self.ext.data.push(b);
self.current_frame_mut().delay = delay;
goto!(Byte(ByteValue::TransparentIdx))
},
(ImageLeft, left) => {
Expand Down Expand Up @@ -534,14 +535,15 @@ impl StreamingDecoder {
},
ControlFlags => {
self.ext.data.push(b);
let frame = self.current_frame_mut();
let control_flags = b;
if control_flags & 1 != 0 {
// Set to Some(...), gets overwritten later
self.current_frame_mut().transparent = Some(0)
frame.transparent = Some(0)
}
self.current_frame_mut().needs_user_input =
frame.needs_user_input =
control_flags & 0b10 != 0;
self.current_frame_mut().dispose = match DisposalMethod::from_u8(
frame.dispose = match DisposalMethod::from_u8(
(control_flags & 0b11100) >> 2
) {
Some(method) => method,
Expand All @@ -560,13 +562,14 @@ impl StreamingDecoder {
let local_table = (b & 0b1000_0000) != 0;
let interlaced = (b & 0b0100_0000) != 0;
let table_size = b & 0b0000_0111;
let check_frame_consistency = self.check_frame_consistency;
let (width, height) = (self.width, self.height);

self.current_frame_mut().interlaced = interlaced;
let frame = self.current_frame_mut();

if self.check_frame_consistency {
frame.interlaced = interlaced;
if check_frame_consistency {
// Consistency checks.
let (width, height) = (self.width, self.height);
let frame = self.current_frame_mut();
if width.checked_sub(frame.width) < Some(frame.left)
|| height.checked_sub(frame.height) < Some(frame.top)
{
Expand All @@ -578,7 +581,7 @@ impl StreamingDecoder {
let entries = PLTE_CHANNELS * (1 << (table_size + 1));
let mut pal = Vec::new();
pal.try_reserve_exact(entries).map_err(|_| io::Error::from(io::ErrorKind::OutOfMemory))?;
self.current_frame_mut().palette = Some(pal);
frame.palette = Some(pal);
goto!(LocalPalette(entries))
} else {
goto!(Byte(CodeSize))
Expand All @@ -594,7 +597,7 @@ impl StreamingDecoder {
goto!(n, GlobalPalette(left - n))
} else {
let idx = self.background_color[0];
match self.global_color_table.chunks(PLTE_CHANNELS).nth(idx as usize) {
match self.global_color_table.chunks_exact(PLTE_CHANNELS).nth(idx as usize) {
Some(chunk) => self.background_color[..PLTE_CHANNELS]
.copy_from_slice(&chunk[..PLTE_CHANNELS]),
None => self.background_color[0] = 0
Expand Down Expand Up @@ -675,9 +678,13 @@ impl StreamingDecoder {
LocalPalette(left) => {
let n = cmp::min(left, buf.len());
if left > 0 {

self.current_frame_mut().palette
.as_mut().unwrap().extend(buf[..n].iter().copied());
let src = &buf[..n];
if let Some(pal) = self.current_frame_mut().palette.as_mut() {
// capacity has already been reserved in ImageFlags
if pal.capacity() - pal.len() >= src.len() {
pal.extend_from_slice(src);
}
}
goto!(n, LocalPalette(left - n))
} else {
goto!(LzwInit(b))
Expand Down

0 comments on commit c33079b

Please sign in to comment.