]> git.lizzy.rs Git - rust.git/commitdiff
rollup merge of #23668: alexcrichton/io-zero
authorAlex Crichton <alex@alexcrichton.com>
Tue, 24 Mar 2015 21:50:48 +0000 (14:50 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Tue, 24 Mar 2015 21:50:48 +0000 (14:50 -0700)
This commit alters the behavior of the `Read::read_to_end()` method to zero all
memory instead of passing an uninitialized buffer to `read`. This change is
motivated by the [discussion on the internals forum][discuss] where the
conclusion has been that the standard library will not expose uninitialized
memory.

[discuss]: http://internals.rust-lang.org/t/uninitialized-memory/1652

Closes #20314

1  2 
src/libstd/io/mod.rs

diff --combined src/libstd/io/mod.rs
index 39c718c96b38a014583a3f557b8c8cdfff9f3fb6,33c4156fc0ce799608567afa1ab37d30bb443632..c6ae4d0dbec7d87d0ce650569fadfd8467cd91f0
@@@ -16,13 -16,12 +16,12 @@@ use cmp
  use unicode::str as core_str;
  use error as std_error;
  use fmt;
- use iter::Iterator;
+ use iter::{self, Iterator, IteratorExt, Extend};
  use marker::Sized;
  use ops::{Drop, FnOnce};
  use option::Option::{self, Some, None};
  use result::Result::{Ok, Err};
  use result;
- use slice;
  use string::String;
  use str;
  use vec::Vec;
@@@ -50,41 -49,26 +49,26 @@@ mod stdio
  const DEFAULT_BUF_SIZE: usize = 64 * 1024;
  
  // Acquires a slice of the vector `v` from its length to its capacity
- // (uninitialized data), reads into it, and then updates the length.
+ // (after initializing the data), reads into it, and then updates the length.
  //
  // This function is leveraged to efficiently read some bytes into a destination
  // vector without extra copying and taking advantage of the space that's already
  // in `v`.
- //
- // The buffer we're passing down, however, is pointing at uninitialized data
- // (the end of a `Vec`), and many operations will be *much* faster if we don't
- // have to zero it out. In order to prevent LLVM from generating an `undef`
- // value when reads happen from this uninitialized memory, we force LLVM to
- // think it's initialized by sending it through a black box. This should prevent
- // actual undefined behavior after optimizations.
  fn with_end_to_cap<F>(v: &mut Vec<u8>, f: F) -> Result<usize>
      where F: FnOnce(&mut [u8]) -> Result<usize>
  {
-     unsafe {
-         let n = try!(f({
-             let base = v.as_mut_ptr().offset(v.len() as isize);
-             black_box(slice::from_raw_parts_mut(base,
-                                                 v.capacity() - v.len()))
-         }));
-         // If the closure (typically a `read` implementation) reported that it
-         // read a larger number of bytes than the vector actually has, we need
-         // to be sure to clamp the vector to at most its capacity.
-         let new_len = cmp::min(v.capacity(), v.len() + n);
-         v.set_len(new_len);
-         return Ok(n);
-     }
-     // Semi-hack used to prevent LLVM from retaining any assumptions about
-     // `dummy` over this function call
-     unsafe fn black_box<T>(mut dummy: T) -> T {
-         asm!("" :: "r"(&mut dummy) : "memory");
-         dummy
+     let len = v.len();
+     let new_area = v.capacity() - len;
+     v.extend(iter::repeat(0).take(new_area));
+     match f(&mut v[len..]) {
+         Ok(n) => {
+             v.truncate(len + n);
+             Ok(n)
+         }
+         Err(e) => {
+             v.truncate(len);
+             Err(e)
+         }
      }
  }
  
@@@ -558,12 -542,6 +542,12 @@@ pub trait BufRead: Read 
      /// This function does not perform any I/O, it simply informs this object
      /// that some amount of its buffer, returned from `fill_buf`, has been
      /// consumed and should no longer be returned.
 +    ///
 +    /// This function is used to tell the buffer how many bytes you've consumed
 +    /// from the return value of `fill_buf`, and so may do odd things if
 +    /// `fill_buf` isn't called before calling this.
 +    ///
 +    /// The `amt` must be `<=` the number of bytes in the buffer returned by `fill_buf`.
      #[stable(feature = "rust1", since = "1.0.0")]
      fn consume(&mut self, amt: usize);