From cb7e9f87eb44e6da02ff39c12c71ae6dddad6bc0 Mon Sep 17 00:00:00 2001 From: Ty Overby Date: Thu, 20 Apr 2017 22:11:28 -0700 Subject: [PATCH 1/2] fix buffer length bug --- src/de/mod.rs | 22 +++------------------- src/de/read.rs | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 19 deletions(-) diff --git a/src/de/mod.rs b/src/de/mod.rs index bbba6c4..b98be7e 100644 --- a/src/de/mod.rs +++ b/src/de/mod.rs @@ -1,4 +1,3 @@ -use std::cmp; use std::io::Read; use std::marker::PhantomData; @@ -12,8 +11,6 @@ use self::read::BincodeRead; pub mod read; -const BLOCK_SIZE: usize = 65536; - /// A Deserializer that reads bytes from a buffer. /// /// This struct should rarely be used. @@ -53,22 +50,9 @@ impl<'de, R: BincodeRead<'de>, E: ByteOrder, S: SizeLimit> Deserializer } fn read_vec(&mut self) -> Result> { - let mut len: usize = try!(serde::Deserialize::deserialize(&mut *self)); - - let mut result = Vec::new(); - let mut off = 0; - while len > 0 { - let reserve = cmp::min(len, BLOCK_SIZE); - try!(self.read_bytes(reserve as u64)); - unsafe { - result.reserve(reserve); - result.set_len(off + reserve); - } - try!(self.reader.read_exact(&mut result[off..])); - len -= reserve; - off += reserve; - } - Ok(result) + let len: usize = try!(serde::Deserialize::deserialize(&mut *self)); + self.read_bytes(len as u64)?; + self.reader.get_byte_buffer(len) } fn read_string(&mut self) -> Result { diff --git a/src/de/read.rs b/src/de/read.rs index 68ee1c5..f39de64 100644 --- a/src/de/read.rs +++ b/src/de/read.rs @@ -9,6 +9,9 @@ pub trait BincodeRead<'storage>: IoRead { fn forward_read_str(&mut self, length: usize, visitor: V) -> Result where V: serde::de::Visitor<'storage>; + #[doc(hidden)] + fn get_byte_buffer(&mut self, length: usize) -> Result>; + #[doc(hidden)] fn forward_read_bytes>(&mut self, length: usize, visitor: V) -> Result where V: serde::de::Visitor<'storage>; @@ -74,6 +77,21 @@ impl <'storage> BincodeRead<'storage> for SliceReader<'storage> { self.slice = &self.slice[length..]; r } + + fn get_byte_buffer(&mut self, length: usize) -> Result> { + use ::ErrorKind; + if length > self.slice.len() { + return Err(Box::new(ErrorKind::InvalidEncoding { + desc: "string was not valid utf8", + detail: None, + })); + } + + let r = &self.slice[..length]; + self.slice = &self.slice[length..]; + Ok(r.to_vec()) + } + fn forward_read_bytes>(&mut self, length: usize, visitor: V) -> Result { use ::ErrorKind; if length > self.slice.len() { @@ -106,10 +124,24 @@ impl BincodeRead<'static> for IoReadReader where R: IoRead { let r = visitor.visit_str(string); r } + + fn get_byte_buffer(&mut self, length: usize) -> Result> { + let current_length = self.temp_buffer.len(); + if length > current_length{ + self.temp_buffer.reserve_exact(length - current_length); + unsafe { self.temp_buffer.set_len(length); } + } + + self.reader.read_exact(&mut self.temp_buffer[..length])?; + + Ok(self.temp_buffer[..length].to_vec()) + } + fn forward_read_bytes>(&mut self, length: usize, visitor: V) -> Result { let current_length = self.temp_buffer.len(); if length > current_length{ self.temp_buffer.reserve_exact(length - current_length); + unsafe { self.temp_buffer.set_len(length); } } self.reader.read_exact(&mut self.temp_buffer[..length])?; From 8be2e87415487333e42798f323ca7547eee413c6 Mon Sep 17 00:00:00 2001 From: Ty Overby Date: Thu, 20 Apr 2017 22:20:56 -0700 Subject: [PATCH 2/2] factor out some common functionality --- src/de/read.rs | 63 +++++++++++++++++++++++++------------------------- 1 file changed, 31 insertions(+), 32 deletions(-) diff --git a/src/de/read.rs b/src/de/read.rs index f39de64..c22ee23 100644 --- a/src/de/read.rs +++ b/src/de/read.rs @@ -13,7 +13,7 @@ pub trait BincodeRead<'storage>: IoRead { fn get_byte_buffer(&mut self, length: usize) -> Result>; #[doc(hidden)] - fn forward_read_bytes>(&mut self, length: usize, visitor: V) -> Result + fn forward_read_bytes(&mut self, length: usize, visitor: V) -> Result where V: serde::de::Visitor<'storage>; } @@ -59,11 +59,18 @@ impl IoRead for IoReadReader { } } +impl <'storage> SliceReader<'storage> { + fn unexpected_eof() -> Box<::ErrorKind> { + return Box::new(::ErrorKind::IoError(IoError::new(IoErrorKind::UnexpectedEof, ""))); + } +} + impl <'storage> BincodeRead<'storage> for SliceReader<'storage> { - fn forward_read_str>(&mut self, length: usize, visitor: V) -> Result { + fn forward_read_str(&mut self, length: usize, visitor: V) -> Result + where V: serde::de::Visitor<'storage> { use ::ErrorKind; if length > self.slice.len() { - return Err(Box::new(ErrorKind::IoError(IoError::new(IoErrorKind::UnexpectedEof, "")))); + return Err(SliceReader::unexpected_eof()); } let string = match ::std::str::from_utf8(&self.slice[..length]) { @@ -79,12 +86,8 @@ impl <'storage> BincodeRead<'storage> for SliceReader<'storage> { } fn get_byte_buffer(&mut self, length: usize) -> Result> { - use ::ErrorKind; if length > self.slice.len() { - return Err(Box::new(ErrorKind::InvalidEncoding { - desc: "string was not valid utf8", - detail: None, - })); + return Err(SliceReader::unexpected_eof()); } let r = &self.slice[..length]; @@ -92,10 +95,10 @@ impl <'storage> BincodeRead<'storage> for SliceReader<'storage> { Ok(r.to_vec()) } - fn forward_read_bytes>(&mut self, length: usize, visitor: V) -> Result { - use ::ErrorKind; + fn forward_read_bytes(&mut self, length: usize, visitor: V) -> Result + where V: serde::de::Visitor<'storage> { if length > self.slice.len() { - return Err(Box::new(ErrorKind::IoError(IoError::new(IoErrorKind::UnexpectedEof, "")))); + return Err(SliceReader::unexpected_eof()); } let r = visitor.visit_borrowed_bytes(&self.slice[..length]); @@ -104,18 +107,27 @@ impl <'storage> BincodeRead<'storage> for SliceReader<'storage> { } } -impl BincodeRead<'static> for IoReadReader where R: IoRead { - fn forward_read_str>(&mut self, length: usize, visitor: V) -> Result { - use ::ErrorKind; +impl IoReadReader where R: IoRead { + fn fill_buffer(&mut self, length: usize) -> Result<()> { let current_length = self.temp_buffer.len(); if length > current_length{ self.temp_buffer.reserve_exact(length - current_length); + unsafe { self.temp_buffer.set_len(length); } } self.reader.read_exact(&mut self.temp_buffer[..length])?; + Ok(()) + } +} + +impl BincodeRead<'static> for IoReadReader where R: IoRead { + fn forward_read_str(&mut self, length: usize, visitor: V) -> Result + where V: serde::de::Visitor<'static> { + self.fill_buffer(length)?; + let string = match ::std::str::from_utf8(&self.temp_buffer[..length]) { Ok(s) => s, - Err(_) => return Err(Box::new(ErrorKind::InvalidEncoding { + Err(_) => return Err(Box::new(::ErrorKind::InvalidEncoding { desc: "string was not valid utf8", detail: None, })), @@ -126,26 +138,13 @@ impl BincodeRead<'static> for IoReadReader where R: IoRead { } fn get_byte_buffer(&mut self, length: usize) -> Result> { - let current_length = self.temp_buffer.len(); - if length > current_length{ - self.temp_buffer.reserve_exact(length - current_length); - unsafe { self.temp_buffer.set_len(length); } - } - - self.reader.read_exact(&mut self.temp_buffer[..length])?; - + self.fill_buffer(length)?; Ok(self.temp_buffer[..length].to_vec()) } - fn forward_read_bytes>(&mut self, length: usize, visitor: V) -> Result { - let current_length = self.temp_buffer.len(); - if length > current_length{ - self.temp_buffer.reserve_exact(length - current_length); - unsafe { self.temp_buffer.set_len(length); } - } - - self.reader.read_exact(&mut self.temp_buffer[..length])?; - + fn forward_read_bytes(&mut self, length: usize, visitor: V) -> Result + where V: serde::de::Visitor<'static> { + self.fill_buffer(length)?; let r = visitor.visit_bytes(&self.temp_buffer[..length]); r }