diff options
| author | Jörn Horstmann <git@jhorstmann.net> | 2022-03-25 11:39:11 +0100 |
|---|---|---|
| committer | Jörn Horstmann <git@jhorstmann.net> | 2022-03-25 11:39:11 +0100 |
| commit | 0cf606177e79bc580fa27a82eb9c8b56e7253f46 (patch) | |
| tree | efb749595e7d47f322a3f86398e17e98f9f7f654 | |
| parent | 4ce257ff198d23bdf14e956fbf2fe0fed297201f (diff) | |
| download | rust-0cf606177e79bc580fa27a82eb9c8b56e7253f46.tar.gz rust-0cf606177e79bc580fa27a82eb9c8b56e7253f46.zip | |
Fix double drop of allocator in IntoIter impl of Vec
| -rw-r--r-- | library/alloc/src/vec/into_iter.rs | 15 | ||||
| -rw-r--r-- | library/alloc/src/vec/mod.rs | 2 |
2 files changed, 10 insertions, 7 deletions
diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index f17b8d71b3a..471042cd717 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -8,7 +8,8 @@ use core::iter::{ FusedIterator, InPlaceIterable, SourceIter, TrustedLen, TrustedRandomAccessNoCoerce, }; use core::marker::PhantomData; -use core::mem::{self}; +use core::mem::{self, ManuallyDrop}; +use core::ops::Deref; use core::ptr::{self, NonNull}; use core::slice::{self}; @@ -32,7 +33,9 @@ pub struct IntoIter< pub(super) buf: NonNull<T>, pub(super) phantom: PhantomData<T>, pub(super) cap: usize, - pub(super) alloc: A, + // the drop impl reconstructs a RawVec from buf, cap and alloc + // to avoid dropping the allocator twice we need to wrap it into ManuallyDrop + pub(super) alloc: ManuallyDrop<A>, pub(super) ptr: *const T, pub(super) end: *const T, } @@ -295,11 +298,11 @@ where impl<T: Clone, A: Allocator + Clone> Clone for IntoIter<T, A> { #[cfg(not(test))] fn clone(&self) -> Self { - self.as_slice().to_vec_in(self.alloc.clone()).into_iter() + self.as_slice().to_vec_in(self.alloc.deref().clone()).into_iter() } #[cfg(test)] fn clone(&self) -> Self { - crate::slice::to_vec(self.as_slice(), self.alloc.clone()).into_iter() + crate::slice::to_vec(self.as_slice(), self.alloc.deref().clone()).into_iter() } } @@ -311,8 +314,8 @@ unsafe impl<#[may_dangle] T, A: Allocator> Drop for IntoIter<T, A> { impl<T, A: Allocator> Drop for DropGuard<'_, T, A> { fn drop(&mut self) { unsafe { - // `IntoIter::alloc` is not used anymore after this - let alloc = ptr::read(&self.0.alloc); + // `IntoIter::alloc` is not used anymore after this and will be dropped by RawVec + let alloc = ManuallyDrop::into_inner(ptr::read(&self.0.alloc)); // RawVec handles deallocation let _ = RawVec::from_raw_parts_in(self.0.buf.as_ptr(), self.0.cap, alloc); } diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 9a66e69bdc0..96857c4bd6f 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -2575,7 +2575,7 @@ impl<T, A: Allocator> IntoIterator for Vec<T, A> { fn into_iter(self) -> IntoIter<T, A> { unsafe { let mut me = ManuallyDrop::new(self); - let alloc = ptr::read(me.allocator()); + let alloc = ManuallyDrop::new(ptr::read(me.allocator())); let begin = me.as_mut_ptr(); let end = if mem::size_of::<T>() == 0 { arith_offset(begin as *const i8, me.len() as isize) as *const T |
