From 7612ad77975331c91aec8ab2a269b31b22668972 Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Tue, 14 Apr 2020 21:35:37 +0200 Subject: [PATCH 1/2] Vec drop and truncate: drop using raw slice *mut [T] By creating a *mut [T] directly (without going through &mut [T]), avoid questions of validity of the contents of the slice. Consider the following risky code: ```rust unsafe { let mut v = Vec::::with_capacity(16); v.set_len(16); } ``` The intention is that with this change, the above snippet will be sound because Vec::drop does no longer produces a mutable slice of the vector's contents. --- src/liballoc/vec.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 7ef281ff208d7..21c387e59e28e 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -741,7 +741,7 @@ impl Vec { return; } let remaining_len = self.len - len; - let s = slice::from_raw_parts_mut(self.as_mut_ptr().add(len), remaining_len); + let s = ptr::slice_from_raw_parts_mut(self.as_mut_ptr().add(len), remaining_len); self.len = len; ptr::drop_in_place(s); } @@ -2379,7 +2379,7 @@ unsafe impl<#[may_dangle] T> Drop for Vec { fn drop(&mut self) { unsafe { // use drop for [T] - ptr::drop_in_place(&mut self[..]); + ptr::drop_in_place(ptr::slice_from_raw_parts_mut(self.as_mut_ptr(), self.len)) } // RawVec handles deallocation } From f654daf3a6681e6d412db1e3203801353b9089c7 Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Tue, 28 Apr 2020 23:31:32 +0200 Subject: [PATCH 2/2] Vec IntoIter: Drop using raw slice Update Vec drop with a comment to explain why we want to use a raw slice, and extend this pattern to also include the Vec's IntoIter. --- src/liballoc/vec.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 21c387e59e28e..edb36dbf22039 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -2379,6 +2379,8 @@ unsafe impl<#[may_dangle] T> Drop for Vec { fn drop(&mut self) { unsafe { // use drop for [T] + // use a raw slice to refer to the elements of the vector as weakest necessary type; + // could avoid questions of validity in certain cases ptr::drop_in_place(ptr::slice_from_raw_parts_mut(self.as_mut_ptr(), self.len)) } // RawVec handles deallocation @@ -2596,7 +2598,11 @@ impl IntoIter { /// ``` #[stable(feature = "vec_into_iter_as_slice", since = "1.15.0")] pub fn as_mut_slice(&mut self) -> &mut [T] { - unsafe { slice::from_raw_parts_mut(self.ptr as *mut T, self.len()) } + unsafe { &mut *self.as_raw_mut_slice() } + } + + fn as_raw_mut_slice(&mut self) -> *mut [T] { + ptr::slice_from_raw_parts_mut(self.ptr as *mut T, self.len()) } } @@ -2708,7 +2714,7 @@ unsafe impl<#[may_dangle] T> Drop for IntoIter { let guard = DropGuard(self); // destroy the remaining elements unsafe { - ptr::drop_in_place(guard.0.as_mut_slice()); + ptr::drop_in_place(guard.0.as_raw_mut_slice()); } // now `guard` will be dropped and do the rest }