diff options
| -rw-r--r-- | src/binary/reader.rs | 15 | ||||
| -rw-r--r-- | tests/fuzzer.rs | 6 | 
2 files changed, 20 insertions, 1 deletions
| diff --git a/src/binary/reader.rs b/src/binary/reader.rs index e8a2bf8..770b12f 100644 --- a/src/binary/reader.rs +++ b/src/binary/reader.rs @@ -40,6 +40,11 @@ pub struct EventReader<R> {      // The largest single allocation allowed for this Plist.      // Equal to the number of bytes in the Plist minus the magic and trailer.      max_allocation: usize, +    // The maximum number of objects that can be created. Default 10 * object_offsets.len(). +    // Binary plists can contain circular references. +    max_objects: usize, +    // The number of objects created so far. +    current_objects: usize,  }  impl<R: Read + Seek> EventReader<R> { @@ -50,7 +55,9 @@ impl<R: Read + Seek> EventReader<R> {              reader: reader,              ref_size: 0,              finished: false, -            max_allocation: 0 +            max_allocation: 0, +            max_objects: 0, +            current_objects: 0,          }      } @@ -92,6 +99,8 @@ impl<R: Read + Seek> EventReader<R> {          try!(self.reader.seek(SeekFrom::Start(offset_table_offset)));          self.object_offsets = try!(self.read_ints(num_objects, offset_size)); +        self.max_objects = self.object_offsets.len() * 10; +          // Seek to top object          self.stack.push(StackItem {              object_refs: vec![top_object], @@ -164,6 +173,10 @@ impl<R: Read + Seek> EventReader<R> {          match object_ref {              Some(object_ref) => { +                if self.current_objects > self.max_objects { +                    return Err(Error::InvalidData); +                } +                self.current_objects += 1;                  try!(self.seek_to_object(object_ref));              }              None => { diff --git a/tests/fuzzer.rs b/tests/fuzzer.rs index 4d7b151..65ce8eb 100644 --- a/tests/fuzzer.rs +++ b/tests/fuzzer.rs @@ -21,6 +21,12 @@ fn empty_offset_table() {      test_fuzzer_data_err(data);  } +#[test] +fn binary_circular_reference() { +    let data = b"bplist00\xd6\x01\x02\x03\x04\x05\x06\x07\x0a\x0b\x0c\x0d\x0eULinesUDeathVHeightYBirthdateVAutbplist00\xd6\x01\x02\x03\x04\x05\x06\x07\x0a\x0b\x0c\x0d\x0eULinesUDeathVHeightYBirthdateVAuthorTData\xa2\x08\x09_\x10\x1eIt is nifying nothing.\x11\x06\x1c#?\xf9\x99\x99\x99\x99\x99\x9a3\xc1\xc2v\x00e\x00\x00\x00_\x10\x13William ShakespeareO\x10\x0f\x00\x00\x00\xbe\x00\x00\x00\x03\x00\x00\x00\x1e\x00\x00\x00\x08\x15\x1b!(58>Ab\x90\x93\x9c\xa5\xbb\x00\x00\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xcd"; +    test_fuzzer_data_err(data); +} +  fn test_fuzzer_data_err(data: &[u8]) {      let cursor = Cursor::new(data);      let res = Plist::read(cursor); | 
