diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/binary/reader.rs | 23 | ||||
| -rw-r--r-- | src/builder.rs | 5 | ||||
| -rw-r--r-- | src/de.rs | 22 | ||||
| -rw-r--r-- | src/lib.rs | 17 |
4 files changed, 52 insertions, 15 deletions
diff --git a/src/binary/reader.rs b/src/binary/reader.rs index 0504e13..128c573 100644 --- a/src/binary/reader.rs +++ b/src/binary/reader.rs @@ -4,7 +4,7 @@ use chrono::{TimeZone, UTC}; use std::io::{Cursor, Read, Seek, SeekFrom}; use std::string::FromUtf16Error; -use {Error, Result, PlistEvent}; +use {Error, Result, PlistEvent, u64_to_usize}; impl From<ByteorderError> for Error { fn from(err: ByteorderError) -> Error { @@ -82,7 +82,8 @@ impl<R: Read + Seek> EventReader<R> { } fn read_ints(&mut self, len: u64, size: u8) -> Result<Vec<u64>> { - let mut ints = Vec::with_capacity(len as usize); + let len = try!(u64_to_usize(len)); + let mut ints = Vec::with_capacity(len); // TODO: Is the match hoisted out of the loop? for _ in 0..len { match size { @@ -117,10 +118,11 @@ impl<R: Read + Seek> EventReader<R> { } fn read_data(&mut self, len: u64) -> Result<Vec<u8>> { - let mut data = vec![0; len as usize]; - let mut total_read = 0usize; + let len = try!(u64_to_usize(len)); + let mut data = vec![0; len]; + let mut total_read = 0; - while (total_read as u64) < len { + while total_read < len { let read = try!(self.reader.read(&mut data[total_read..])); if read == 0 { return Err(Error::UnexpectedEof); @@ -132,7 +134,8 @@ impl<R: Read + Seek> EventReader<R> { } fn seek_to_object(&mut self, object_ref: u64) -> Result<u64> { - let offset = *&self.object_offsets[object_ref as usize]; + let object_ref = try!(u64_to_usize(object_ref)); + let offset = *&self.object_offsets[object_ref]; let pos = try!(self.reader.seek(SeekFrom::Start(offset))); Ok(pos) } @@ -221,7 +224,8 @@ impl<R: Read + Seek> EventReader<R> { let raw = try!(self.read_data(len)); let mut cursor = Cursor::new(raw); - let mut raw_utf16 = Vec::with_capacity(len as usize / 2); + let len_div_2 = try!(u64_to_usize(len / 2)); + let mut raw_utf16 = Vec::with_capacity(len_div_2); while cursor.position() < len { raw_utf16.push(try!(cursor.read_u16::<BigEndian>())) } @@ -249,9 +253,10 @@ impl<R: Read + Seek> EventReader<R> { let key_refs = try!(self.read_refs(len)); let value_refs = try!(self.read_refs(len)); - let len = len as usize; + let len_mul_2 = try!(u64_to_usize(len * 2)); + let len = try!(u64_to_usize(len)); - let mut object_refs = Vec::with_capacity(len * 2); + let mut object_refs = Vec::with_capacity(len_mul_2); for i in 1..len + 1 { // Reverse so we can pop off the end of the stack in order diff --git a/src/builder.rs b/src/builder.rs index db56ee8..6ce78c5 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -1,6 +1,6 @@ use std::collections::BTreeMap; -use {Error, Result, Plist, PlistEvent}; +use {Error, Result, Plist, PlistEvent, u64_option_to_usize}; pub struct Builder<T> { stream: T, @@ -67,8 +67,9 @@ impl<T: Iterator<Item = Result<PlistEvent>>> Builder<T> { } fn build_array(&mut self, len: Option<u64>) -> Result<Vec<Plist>> { + let len = try!(u64_option_to_usize(len)); let mut values = match len { - Some(len) => Vec::with_capacity(len as usize), + Some(len) => Vec::with_capacity(len), None => Vec::new(), }; @@ -5,7 +5,7 @@ use serde::de::{Deserializer as SerdeDeserializer, Error as SerdeError, Visitor, MapVisitor, VariantVisitor, Deserialize, EnumVisitor}; use std::iter::Peekable; -use PlistEvent; +use {PlistEvent, u64_option_to_usize}; macro_rules! expect { ($next:expr, $pat:pat) => { @@ -39,6 +39,12 @@ pub enum Error { None, } +impl From<::Error> for Error { + fn from(_: ::Error) -> Error { + Error::None + } +} + impl SerdeError for Error { fn syntax(_msg: &str) -> Self { panic!("stx"); @@ -87,12 +93,14 @@ impl<I, E> SerdeDeserializer for Deserializer<I, E> PlistEvent::EndPlist => panic!(), PlistEvent::StartArray(len) => { - visitor.visit_seq(MapSeq::new(self, len.map(|l| l as usize))) + let len = try!(u64_option_to_usize(len)); + visitor.visit_seq(MapSeq::new(self, len)) } PlistEvent::EndArray => return Err(Error::syntax("")), PlistEvent::StartDictionary(len) => { - visitor.visit_map(MapSeq::new(self, len.map(|l| l as usize))) + let len = try!(u64_option_to_usize(len)); + visitor.visit_map(MapSeq::new(self, len)) } PlistEvent::EndDictionary => return Err(Error::syntax("")), @@ -120,7 +128,13 @@ impl<I, E> SerdeDeserializer for Deserializer<I, E> let ret = match try_next!(self.events.next()) { PlistEvent::StringValue(ref s) if &s[..] == "None" => { - let ret = try!(visitor.visit_none()); + let ret = match visitor.visit_none() { + Ok(ret) => ret, + Err(e) => return Err(e) + }; + // For some reason the try! below doesn't work - probably a macro hygene issue + // with Error and ::Error + //let ret = try!(visitor.visit_none()); expect!(self.events.next(), PlistEvent::StringValue(_)); ret } @@ -157,6 +157,8 @@ pub enum PlistEvent { StartPlist, EndPlist, + // While the length of an array or dict cannot be feasably greater than max(usize) this better + // conveys the concept of an effectively unbounded event stream. StartArray(Option<u64>), EndArray, @@ -286,3 +288,18 @@ impl<R: Read + Seek> Iterator for EventReader<R> { pub trait EventWriter { fn write(&mut self, event: &PlistEvent) -> Result<()>; } + +fn u64_to_usize(len_u64: u64) -> Result<usize> { + let len = len_u64 as usize; + if len as u64 != len_u64 { + return Err(Error::InvalidData); // Too long + } + Ok(len) +} + +fn u64_option_to_usize(len: Option<u64>) -> Result<Option<usize>> { + match len { + Some(len) => Ok(Some(try!(u64_to_usize(len)))), + None => Ok(None), + } +} |
