1
Fork 0

Rollup merge of #61230 - matklad:ub-comment, r=RalfJung

avoid creating Boxes of uninitalized values in RawVec

`RawVec<bool>::into_box` is definitely instant UB, if not all values are initialized.

See https://gankro.github.io/blah/initialize-me-maybe/
This commit is contained in:
Mazdak Farrokhzad 2019-05-28 11:48:58 +02:00 committed by GitHub
commit 460e626a9c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 15 additions and 11 deletions

View file

@ -395,11 +395,10 @@ impl<T: Clone> Clone for Box<T> {
#[stable(feature = "box_slice_clone", since = "1.3.0")]
impl Clone for Box<str> {
fn clone(&self) -> Self {
let len = self.len();
let buf = RawVec::with_capacity(len);
// this makes a copy of the data
let buf: Box<[u8]> = self.as_bytes().into();
unsafe {
ptr::copy_nonoverlapping(self.as_ptr(), buf.ptr(), len);
from_boxed_utf8_unchecked(buf.into_box())
from_boxed_utf8_unchecked(buf)
}
}
}
@ -546,9 +545,12 @@ impl<T: Copy> From<&[T]> for Box<[T]> {
/// println!("{:?}", boxed_slice);
/// ```
fn from(slice: &[T]) -> Box<[T]> {
let mut boxed = unsafe { RawVec::with_capacity(slice.len()).into_box() };
boxed.copy_from_slice(slice);
boxed
let len = slice.len();
let buf = RawVec::with_capacity(len);
unsafe {
ptr::copy_nonoverlapping(slice.as_ptr(), buf.ptr(), len);
buf.into_box()
}
}
}

View file

@ -685,12 +685,14 @@ impl<T, A: Alloc> RawVec<T, A> {
impl<T> RawVec<T, Global> {
/// Converts the entire buffer into `Box<[T]>`.
///
/// While it is not *strictly* Undefined Behavior to call
/// this procedure while some of the RawVec is uninitialized,
/// it certainly makes it trivial to trigger it.
///
/// Note that this will correctly reconstitute any `cap` changes
/// that may have been performed. (see description of type for details)
///
/// # Undefined Behavior
///
/// All elements of `RawVec<T, Global>` must be initialized. Notice that
/// the rules around uninitialized boxed values are not finalized yet,
/// but until they are, it is advisable to avoid them.
pub unsafe fn into_box(self) -> Box<[T]> {
// NOTE: not calling `cap()` here, actually using the real `cap` field!
let slice = slice::from_raw_parts_mut(self.ptr(), self.cap);