aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/binary/reader.rs23
-rw-r--r--src/builder.rs5
-rw-r--r--src/de.rs22
-rw-r--r--src/lib.rs17
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(),
};
diff --git a/src/de.rs b/src/de.rs
index 4290254..9affd01 100644
--- a/src/de.rs
+++ b/src/de.rs
@@ -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
}
diff --git a/src/lib.rs b/src/lib.rs
index 5f3275f..def6bfd 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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),
+ }
+}