Skip to content

Commit 460e626

Browse files
authored
Rollup merge of rust-lang#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/
2 parents c48835b + fe31ad3 commit 460e626

File tree

2 files changed

+15
-11
lines changed

2 files changed

+15
-11
lines changed

src/liballoc/boxed.rs

+9-7
Original file line numberDiff line numberDiff line change
@@ -395,11 +395,10 @@ impl<T: Clone> Clone for Box<T> {
395395
#[stable(feature = "box_slice_clone", since = "1.3.0")]
396396
impl Clone for Box<str> {
397397
fn clone(&self) -> Self {
398-
let len = self.len();
399-
let buf = RawVec::with_capacity(len);
398+
// this makes a copy of the data
399+
let buf: Box<[u8]> = self.as_bytes().into();
400400
unsafe {
401-
ptr::copy_nonoverlapping(self.as_ptr(), buf.ptr(), len);
402-
from_boxed_utf8_unchecked(buf.into_box())
401+
from_boxed_utf8_unchecked(buf)
403402
}
404403
}
405404
}
@@ -546,9 +545,12 @@ impl<T: Copy> From<&[T]> for Box<[T]> {
546545
/// println!("{:?}", boxed_slice);
547546
/// ```
548547
fn from(slice: &[T]) -> Box<[T]> {
549-
let mut boxed = unsafe { RawVec::with_capacity(slice.len()).into_box() };
550-
boxed.copy_from_slice(slice);
551-
boxed
548+
let len = slice.len();
549+
let buf = RawVec::with_capacity(len);
550+
unsafe {
551+
ptr::copy_nonoverlapping(slice.as_ptr(), buf.ptr(), len);
552+
buf.into_box()
553+
}
552554
}
553555
}
554556

src/liballoc/raw_vec.rs

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

0 commit comments

Comments
 (0)