Skip to content

Commit 323ef4b

Browse files
committed
Fix off-by-one in sub_block_lens
1 parent 901951b commit 323ef4b

File tree

2 files changed

+19
-17
lines changed

2 files changed

+19
-17
lines changed

src/reader/decoder.rs

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ use weezl::{decode::Decoder as LzwDecoder, BitOrder, LzwError, LzwStatus};
1919
/// GIF palettes are RGB
2020
pub const PLTE_CHANNELS: usize = 3;
2121
/// Headers for supported extensions.
22-
const EXT_NAME_NETSCAPE: &[u8] = b"\x0bNETSCAPE2.0\x01";
23-
const EXT_NAME_XMP: &[u8] = b"\x0bXMP DataXMP";
24-
const EXT_NAME_ICC: &[u8] = b"\x0bICCRGBG1012";
22+
const EXT_NAME_NETSCAPE: &[u8] = b"NETSCAPE2.0\x01";
23+
const EXT_NAME_XMP: &[u8] = b"XMP DataXMP";
24+
const EXT_NAME_ICC: &[u8] = b"ICCRGBG1012";
2525

2626
/// An error returned in the case of the image not being formatted properly.
2727
#[derive(Debug)]
@@ -719,12 +719,10 @@ impl StreamingDecoder {
719719
self.ext.data.clear();
720720
self.ext.sub_block_lens.clear();
721721
self.ext.id = AnyExtension(b);
722-
if self.ext.id.into_known().is_none() {
723-
if !self.allow_unknown_blocks {
724-
return Err(DecodingError::format(
725-
"unknown extension block encountered",
726-
));
727-
}
722+
if !self.allow_unknown_blocks && self.ext.id.into_known().is_none() {
723+
return Err(DecodingError::format(
724+
"unknown extension block encountered",
725+
));
728726
}
729727
goto!(ExtensionBlockStart, emit Decoded::BlockStart(Block::Extension))
730728
}
@@ -751,7 +749,7 @@ impl StreamingDecoder {
751749
}
752750
}
753751
ExtensionBlockStart => {
754-
self.ext.data.push(b);
752+
self.ext.sub_block_lens.push(b);
755753
goto!(ExtensionDataBlock(b as usize))
756754
}
757755
ExtensionDataBlock(left) => {
@@ -879,10 +877,10 @@ impl StreamingDecoder {
879877
}
880878

881879
fn read_control_extension(&mut self) -> Result<(), DecodingError> {
882-
if self.ext.data.len() != 5 {
880+
if self.ext.data.len() != 4 {
883881
return Err(DecodingError::format("control extension has wrong length"));
884882
}
885-
let control = &self.ext.data[1..];
883+
let control = &self.ext.data;
886884

887885
let frame = self.current.get_or_insert_with(Frame::default);
888886
let control_flags = control[0];
@@ -905,12 +903,16 @@ impl StreamingDecoder {
905903
Repeat::Finite(repeat)
906904
}));
907905
} else if let Some(mut rest) = self.ext.data.strip_prefix(EXT_NAME_XMP) {
906+
let (&id_len, data_lens) = self.ext.sub_block_lens.split_first()?;
907+
if id_len as usize != EXT_NAME_XMP.len() {
908+
return None;
909+
}
908910
// XMP is not written as a valid "pascal-string", so we need to stitch together
909911
// the text from our collected sublock-lengths.
910-
let mut xmp_metadata = Vec::new();
911-
for len in self.ext.sub_block_lens.iter() {
912-
xmp_metadata.push(*len);
913-
let (sub_block, tail) = rest.split_at(*len as usize);
912+
let mut xmp_metadata = Vec::with_capacity(data_lens.len() + self.ext.data.len());
913+
for &len in data_lens {
914+
xmp_metadata.push(len);
915+
let (sub_block, tail) = rest.split_at(len as usize);
914916
xmp_metadata.extend_from_slice(sub_block);
915917
rest = tail;
916918
}

tests/decode.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,5 +305,5 @@ fn check_last_extension_returns() {
305305
}
306306
}
307307

308-
assert_eq!(decoder.last_ext().1.len(), 3048);
308+
assert_eq!(decoder.last_ext().1.len(), 3047);
309309
}

0 commit comments

Comments
 (0)