Implement cycle checking in IFD offsets
This commit is contained in:
1 parent
2c9e02d347
commit
885d762def
3 files changed
+16
-17
No files matched your search
+9
-3
@@ -1,4 +1,4 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::io::{self, Read, Seek};
|
use std::io::{self, Read, Seek};
|
||||||
use std::{cmp, ops::Range};
|
use std::{cmp, ops::Range};
|
||||||
@@ -378,6 +378,7 @@ where
|
|||||||
strip_decoder: Option<StripDecodeState>,
|
strip_decoder: Option<StripDecodeState>,
|
||||||
tile_decoder: Option<TileDecodeState>,
|
tile_decoder: Option<TileDecodeState>,
|
||||||
tile_attributes: Option<TileAttributes>,
|
tile_attributes: Option<TileAttributes>,
|
||||||
|
seen_ifds: HashSet<u64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
trait Wrapping {
|
trait Wrapping {
|
||||||
@@ -544,6 +545,7 @@ impl<R: Read + Seek> Decoder<R> {
|
|||||||
strip_decoder: None,
|
strip_decoder: None,
|
||||||
tile_decoder: None,
|
tile_decoder: None,
|
||||||
tile_attributes: None,
|
tile_attributes: None,
|
||||||
|
seen_ifds: HashSet::new(),
|
||||||
}
|
}
|
||||||
.init()
|
.init()
|
||||||
}
|
}
|
||||||
@@ -640,7 +642,7 @@ impl<R: Read + Seek> Decoder<R> {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.next_ifd = match self.read_ifd_offset()? {
|
self.next_ifd = match self.read_ifd_offset_nonrepeating()? {
|
||||||
0 => None,
|
0 => None,
|
||||||
n => Some(n),
|
n => Some(n),
|
||||||
};
|
};
|
||||||
@@ -738,7 +740,11 @@ impl<R: Read + Seek> Decoder<R> {
|
|||||||
|
|
||||||
fn read_ifd_offset_nonrepeating(&mut self) -> TiffResult<u64> {
|
fn read_ifd_offset_nonrepeating(&mut self) -> TiffResult<u64> {
|
||||||
let result = self.read_ifd_offset()?;
|
let result = self.read_ifd_offset()?;
|
||||||
|
if self.seen_ifds.insert(result) {
|
||||||
Ok(result)
|
Ok(result)
|
||||||
|
} else {
|
||||||
|
Err(TiffError::FormatError(TiffFormatError::CycleInOffsets))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -899,7 +905,7 @@ impl<R: Read + Seek> Decoder<R> {
|
|||||||
};
|
};
|
||||||
dir.insert(tag, entry);
|
dir.insert(tag, entry);
|
||||||
}
|
}
|
||||||
self.next_ifd = match self.read_ifd_offset()? {
|
self.next_ifd = match self.read_ifd_offset_nonrepeating()? {
|
||||||
0 => None,
|
0 => None,
|
||||||
n => Some(n),
|
n => Some(n),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ pub enum TiffFormatError {
|
|||||||
Format(String),
|
Format(String),
|
||||||
RequiredTagEmpty(Tag),
|
RequiredTagEmpty(Tag),
|
||||||
StripTileTagConflict,
|
StripTileTagConflict,
|
||||||
|
CycleInOffsets,
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
/// Do not match against this variant. It may get removed.
|
/// Do not match against this variant. It may get removed.
|
||||||
__NonExhaustive,
|
__NonExhaustive,
|
||||||
@@ -115,6 +116,7 @@ impl fmt::Display for TiffFormatError {
|
|||||||
Format(ref val) => write!(fmt, "Invalid format: {:?}.", val),
|
Format(ref val) => write!(fmt, "Invalid format: {:?}.", val),
|
||||||
RequiredTagEmpty(ref val) => write!(fmt, "Required tag {:?} was empty.", val),
|
RequiredTagEmpty(ref val) => write!(fmt, "Required tag {:?} was empty.", val),
|
||||||
StripTileTagConflict => write!(fmt, "File should contain either (StripByteCounts and StripOffsets) or (TileByteCounts and TileOffsets), other combination was found."),
|
StripTileTagConflict => write!(fmt, "File should contain either (StripByteCounts and StripOffsets) or (TileByteCounts and TileOffsets), other combination was found."),
|
||||||
|
CycleInOffsets => write!(fmt, "File contained a cycle in the list of IFDs"),
|
||||||
__NonExhaustive => unreachable!(),
|
__NonExhaustive => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-14
@@ -498,7 +498,7 @@ fn multiple_images_strip_height() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn timeout() {
|
fn timeout() {
|
||||||
use tiff::TiffError;
|
use tiff::{TiffError, TiffFormatError};
|
||||||
|
|
||||||
let image = [
|
let image = [
|
||||||
73, 73, 42, 0, 8, 0, 0, 0, 16, 0, 254, 0, 4, 0, 1, 68, 0, 0, 0, 2, 0, 32, 254, 252, 0, 109,
|
73, 73, 42, 0, 8, 0, 0, 0, 16, 0, 254, 0, 4, 0, 1, 68, 0, 0, 0, 2, 0, 32, 254, 252, 0, 109,
|
||||||
@@ -511,21 +511,12 @@ fn timeout() {
|
|||||||
0, 0, 73, 73, 42, 0, 8, 0, 0, 0, 0, 0, 32,
|
0, 0, 73, 73, 42, 0, 8, 0, 0, 0, 0, 0, 32,
|
||||||
];
|
];
|
||||||
|
|
||||||
let mut decoder = tiff::decoder::Decoder::new(std::io::Cursor::new(&image)).unwrap();
|
let error = tiff::decoder::Decoder::new(std::io::Cursor::new(&image)).unwrap_err();
|
||||||
|
|
||||||
loop {
|
match error {
|
||||||
decoder.next_image().unwrap();
|
TiffError::FormatError(TiffFormatError::CycleInOffsets) => {}
|
||||||
assert!(decoder.more_images());
|
e => panic!("Unexpected error {:?}", e),
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
let err = decoder.read_image().unwrap_err();
|
|
||||||
|
|
||||||
match err {
|
|
||||||
TiffError::IntSizeError => {}
|
|
||||||
unexpected => panic!("Unexpected error {}", unexpected),
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
Reference in new issue
Block a user