improve safety of fill_buffer - see issue #260

This commit is contained in:
Josh Mcguigan 2019-10-30 05:18:08 -07:00 committed by Josh Matthews
parent 293e9cea32
commit c06b18abed
1 changed files with 18 additions and 2 deletions

View File

@ -1,6 +1,6 @@
use error::Result;
use serde;
use std::io;
use std::{io, slice};
/// An optional Read trait for advanced Bincode usage.
///
@ -136,16 +136,32 @@ where
R: io::Read,
{
fn fill_buffer(&mut self, length: usize) -> Result<()> {
// We first reserve the space needed in our buffer.
let current_length = self.temp_buffer.len();
if length > current_length {
self.temp_buffer.reserve_exact(length - current_length);
}
// Then create a slice with the length as our desired length. This is
// safe as long as we only write (no reads) to this buffer, because
// `reserve_exact` above has allocated this space.
let buf = unsafe {
slice::from_raw_parts_mut(self.temp_buffer.as_mut_ptr(), length)
};
// This method is assumed to properly handle slices which include
// uninitialized bytes (as ours does). See discussion at the link below.
// https://github.com/servo/bincode/issues/260
self.reader.read_exact(buf)?;
// Only after `read_exact` successfully returns do we set the buffer
// length. By doing this after the call to `read_exact`, we can avoid
// exposing uninitialized memory in the case of `read_exact` returning
// an error.
unsafe {
self.temp_buffer.set_len(length);
}
self.reader.read_exact(&mut self.temp_buffer)?;
Ok(())
}
}