ebarnard / rust-plist

A rusty plist parser.
MIT License
71 stars 42 forks source link

Cannot read an empty binary plist #20

Closed kennytm closed 7 years ago

kennytm commented 7 years ago

Test case: (file is taken from iOS 10.3 file system image)

extern crate plist;
use std::io::Cursor;
pub fn main() {
    let empty_plist = b"bplist00\xd0\x08\0\0\0\0\0\0\x01\x01\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\t";
    plist::Plist::read(Cursor::new(&empty_plist[..])).unwrap();
}

Expected: The program finishes with no error. Actual: The program panics with:

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: InvalidData', src/libcore/result.rs:859
note: Run with `RUST_BACKTRACE=1` for a backtrace.

Please compare with Python 3's plistlib:

>>> import plistlib
>>> plistlib.loads(b"bplist00\xd0\x08\0\0\0\0\0\0\x01\x01\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\t")
{}

Tested with commit 1df5db00 (current master)

$ rustc -vV
rustc 1.18.0-nightly (28a742997 2017-04-13)
binary: rustc
commit-hash: 28a74299778cdad4ea999e4ee8f8c1ef793338bd
commit-date: 2017-04-13
host: x86_64-apple-darwin
release: 1.18.0-nightly
LLVM version: 3.9
kennytm commented 7 years ago

The InvalidData is thrown from this line https://github.com/ebarnard/rust-plist/blob/1df5db005ea9959c4e19107997f446dc17095be4/src/binary/reader.rs#L73:

    fn allocate_vec<T>(&self, len: u64) -> Result<Vec<T>> {
        if self.can_allocate::<T>(len) {
            Ok(Vec::with_capacity(len as usize))
        } else {
            Err(Error::InvalidData)
        }
    }

here, len == 1, T == u64 and self.max_allocation == 2, thus 1*8 > 2 and can_allocate() returns false.

Probably the 6-byte padding in the trailing should be counted towards the max_allocation.

Relevant stack trace:

   0: <plist::binary::reader::EventReader<R>>::allocate_vec
   1: <plist::binary::reader::EventReader<R>>::read_ints
   2: <plist::binary::reader::EventReader<R>>::read_trailer
   3: <plist::binary::reader::EventReader<R>>::read_next
   4: <plist::binary::reader::EventReader<R> as core::iter::iterator::Iterator>::next
ebarnard commented 7 years ago

Thanks for the report. Fixed in 0.1.3.