mirror of
https://github.com/storytold/lightcraft.git
synced 2026-10-14 19:27:01 -04:00
Merge PR #1544
This commit is contained in:
commit
c8f1ecd4d3
2 files changed
+38
-3
No files matched your search
@@ -140,9 +140,10 @@ impl<'a> Ctx<'a> {
|
||||
}
|
||||
entries.sort_by_key(|e| e.tag);
|
||||
entries.dedup_by_key(|e| e.tag);
|
||||
let next_pos = table + (n as usize).saturating_mul(entry_size);
|
||||
let next = if n as usize == n_read {
|
||||
match self.read_off(next_pos) {
|
||||
// the next-IFD offset follows the whole table, so only a table read in full has one: a count far past the
|
||||
// file (a BigTIFF's is 64-bit) must not reach the arithmetic (issue #1516)
|
||||
let next = if n == n_read as u64 {
|
||||
match n_read.checked_mul(entry_size).and_then(|len| table.checked_add(len)).and_then(|p| self.read_off(p)) {
|
||||
Some(0) | None => 0,
|
||||
Some(v) => base.checked_add(v).unwrap_or(0),
|
||||
}
|
||||
|
||||
@@ -393,3 +393,37 @@ proptest! {
|
||||
prop_assert_eq!(t.ifds[0].f64s(501).unwrap().len(), v.len());
|
||||
}
|
||||
}
|
||||
|
||||
/// A BigTIFF whose IFD says it has an enormous number of entries, with one readable, computed where the next-IFD
|
||||
/// offset would be from the advertised count: an add overflow, a panic in builds with overflow checks (issue
|
||||
/// #1516). The readable entry is kept and there is no next IFD; complete chains still link.
|
||||
#[test]
|
||||
fn bigtiff_with_an_enormous_entry_count_does_not_panic() {
|
||||
for order in ORDERS {
|
||||
for count in [u64::MAX, 1 << 62, 2] {
|
||||
// little-endian bytes, reversed for big-endian files
|
||||
let e = |le: &[u8]| -> Vec<u8> { if order == ByteOrder::Little { le.to_vec() } else { le.iter().rev().copied().collect() } };
|
||||
let mut f = if order == ByteOrder::Little { b"II".to_vec() } else { b"MM".to_vec() };
|
||||
for part in [e(&43u16.to_le_bytes()), e(&8u16.to_le_bytes()), e(&0u16.to_le_bytes()), e(&16u64.to_le_bytes()), e(&count.to_le_bytes())] {
|
||||
f.extend(part);
|
||||
}
|
||||
// one entry: ImageWidth, LONG, 1 value (inline in the 8-byte field)
|
||||
for part in [e(&tags::IMAGE_WIDTH.to_le_bytes()), e(&4u16.to_le_bytes()), e(&1u64.to_le_bytes()), e(&640u32.to_le_bytes())] {
|
||||
f.extend(part);
|
||||
}
|
||||
f.extend([0; 4]);
|
||||
let (ifd, next) = parse_ifd_at(&f, 16, order, 0, true, &ParseOptions::default()).unwrap();
|
||||
assert_eq!(ifd.value(tags::IMAGE_WIDTH), Some(&Value::Long(vec![640])), "{order:?} {count}");
|
||||
assert_eq!(next, 0, "{order:?} {count}");
|
||||
let t = Tiff::parse(&f).unwrap();
|
||||
assert_eq!(t.ifds.len(), 1);
|
||||
}
|
||||
// a complete chain of two IFDs still links
|
||||
let mut a = IfdBuilder::new();
|
||||
a.set(1000, Value::Short(vec![1]));
|
||||
let mut b = IfdBuilder::new();
|
||||
b.set(1000, Value::Short(vec![2]));
|
||||
let t = Tiff::parse(&TiffWriter::new(order, true).write(&[a, b]).unwrap()).unwrap();
|
||||
assert_eq!(t.ifds.len(), 2, "{order:?}");
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user