From a23a77fb19b24adb22d0a3d3886acac1a7a31f68 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Mon, 27 May 2019 09:43:20 +0300 Subject: [PATCH 1/3] avoid materializing unintialized Boxes in RawVec --- src/liballoc/boxed.rs | 9 ++++++--- src/liballoc/raw_vec.rs | 10 ++++++---- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index bf8f5b8b91a1e..5affdbdb7e9d1 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -546,9 +546,12 @@ impl 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() + } } } diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index d1fc5ac3b30d4..0454a56443579 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -685,12 +685,14 @@ impl RawVec { impl RawVec { /// 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` 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); From 0653e78ae1b35eb50e06423052a34d807f1ac2af Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Mon, 27 May 2019 09:43:20 +0300 Subject: [PATCH 2/3] make Box::clone simpler & safer --- src/liballoc/boxed.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 5affdbdb7e9d1..2f45ec7d643f8 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -395,11 +395,9 @@ impl Clone for Box { #[stable(feature = "box_slice_clone", since = "1.3.0")] impl Clone for Box { fn clone(&self) -> Self { - let len = self.len(); - let buf = RawVec::with_capacity(len); + 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) } } } From fe31ad38cb5c6fba5be871ab63082d7cdf430374 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Mon, 27 May 2019 22:42:50 +0300 Subject: [PATCH 3/3] Update src/liballoc/boxed.rs Co-Authored-By: Ralf Jung --- src/liballoc/boxed.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 2f45ec7d643f8..76b660fba685c 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -395,6 +395,7 @@ impl Clone for Box { #[stable(feature = "box_slice_clone", since = "1.3.0")] impl Clone for Box { fn clone(&self) -> Self { + // this makes a copy of the data let buf: Box<[u8]> = self.as_bytes().into(); unsafe { from_boxed_utf8_unchecked(buf)