Skip to content

Commit 4ccf374

Browse files
committed
std: Zero memory when calling read_to_end()
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 parent 28a0b25 commit 4ccf374

File tree

1 file changed

+14
-30
lines changed

1 file changed

+14
-30
lines changed

src/libstd/io/mod.rs

+14-30
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,12 @@ use cmp;
1616
use unicode::str as core_str;
1717
use error as std_error;
1818
use fmt;
19-
use iter::Iterator;
19+
use iter::{self, Iterator, IteratorExt, Extend};
2020
use marker::Sized;
2121
use ops::{Drop, FnOnce};
2222
use option::Option::{self, Some, None};
2323
use result::Result::{Ok, Err};
2424
use result;
25-
use slice;
2625
use string::String;
2726
use str;
2827
use vec::Vec;
@@ -50,41 +49,26 @@ mod stdio;
5049
const DEFAULT_BUF_SIZE: usize = 64 * 1024;
5150

5251
// Acquires a slice of the vector `v` from its length to its capacity
53-
// (uninitialized data), reads into it, and then updates the length.
52+
// (after initializing the data), reads into it, and then updates the length.
5453
//
5554
// This function is leveraged to efficiently read some bytes into a destination
5655
// vector without extra copying and taking advantage of the space that's already
5756
// in `v`.
58-
//
59-
// The buffer we're passing down, however, is pointing at uninitialized data
60-
// (the end of a `Vec`), and many operations will be *much* faster if we don't
61-
// have to zero it out. In order to prevent LLVM from generating an `undef`
62-
// value when reads happen from this uninitialized memory, we force LLVM to
63-
// think it's initialized by sending it through a black box. This should prevent
64-
// actual undefined behavior after optimizations.
6557
fn with_end_to_cap<F>(v: &mut Vec<u8>, f: F) -> Result<usize>
6658
where F: FnOnce(&mut [u8]) -> Result<usize>
6759
{
68-
unsafe {
69-
let n = try!(f({
70-
let base = v.as_mut_ptr().offset(v.len() as isize);
71-
black_box(slice::from_raw_parts_mut(base,
72-
v.capacity() - v.len()))
73-
}));
74-
75-
// If the closure (typically a `read` implementation) reported that it
76-
// read a larger number of bytes than the vector actually has, we need
77-
// to be sure to clamp the vector to at most its capacity.
78-
let new_len = cmp::min(v.capacity(), v.len() + n);
79-
v.set_len(new_len);
80-
return Ok(n);
81-
}
82-
83-
// Semi-hack used to prevent LLVM from retaining any assumptions about
84-
// `dummy` over this function call
85-
unsafe fn black_box<T>(mut dummy: T) -> T {
86-
asm!("" :: "r"(&mut dummy) : "memory");
87-
dummy
60+
let len = v.len();
61+
let new_area = v.capacity() - len;
62+
v.extend(iter::repeat(0).take(new_area));
63+
match f(&mut v[len..]) {
64+
Ok(n) => {
65+
v.truncate(len + n);
66+
Ok(n)
67+
}
68+
Err(e) => {
69+
v.truncate(len);
70+
Err(e)
71+
}
8872
}
8973
}
9074

0 commit comments

Comments
 (0)