From 4f808161bc2852bff52cf3dd1bb4baf3003ef181 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Sun, 19 Dec 2021 00:18:31 -0500 Subject: [PATCH 1/2] Implement split_at_spare_mut directly The previous implementation used slice::as_mut_ptr_range to derive the pointer for the spare capacity slice. This is invalid, because that pointer is derived from the initialized region, so it does not have provenance over the uninitialized region. --- library/alloc/src/vec/mod.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index d24b4bdffdefc..a55fce2760f97 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -2141,12 +2141,15 @@ impl Vec { unsafe fn split_at_spare_mut_with_len( &mut self, ) -> (&mut [T], &mut [MaybeUninit], &mut usize) { - let Range { start: ptr, end: spare_ptr } = self.as_mut_ptr_range(); + let ptr = self.as_mut_ptr(); + // SAFETY: + // - `ptr` is guaranteed to be valid for `self.len` elements + let spare_ptr = unsafe { ptr.add(self.len) }; let spare_ptr = spare_ptr.cast::>(); let spare_len = self.buf.capacity() - self.len; // SAFETY: - // - `ptr` is guaranteed to be valid for `len` elements + // - `ptr` is guaranteed to be valid for `self.len` elements // - `spare_ptr` is pointing one element past the buffer, so it doesn't overlap with `initialized` unsafe { let initialized = slice::from_raw_parts_mut(ptr, self.len); From 777c853b4a8274b293f30c029cc18bccedde9ecf Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Fri, 31 Dec 2021 18:03:07 -0500 Subject: [PATCH 2/2] Clarify safety comment --- library/alloc/src/vec/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index a55fce2760f97..a6e7f08b00bcf 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -2144,6 +2144,8 @@ impl Vec { let ptr = self.as_mut_ptr(); // SAFETY: // - `ptr` is guaranteed to be valid for `self.len` elements + // - but the allocation extends out to `self.buf.capacity()` elements, possibly + // uninitialized let spare_ptr = unsafe { ptr.add(self.len) }; let spare_ptr = spare_ptr.cast::>(); let spare_len = self.buf.capacity() - self.len;