diff options
| author | Edward Barnard | 2015-12-25 01:16:23 +0000 | 
|---|---|---|
| committer | Edward Barnard | 2015-12-25 10:58:40 +0000 | 
| commit | 35ee8e80f25d852620061fc6e9627485467d12ea (patch) | |
| tree | 0cc6071d933548fad8f2c2c25012c1a2c7f34ec0 | |
| parent | bce38e77de935d1d06ab220dacc8870a3362b80a (diff) | |
| download | rust-plist-35ee8e80f25d852620061fc6e9627485467d12ea.tar.bz2 | |
Better handling of u64 to usize conversions
| -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), +    } +} | 
