about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--library/alloc/src/vec/drain.rs10
1 files changed, 6 insertions, 4 deletions
diff --git a/library/alloc/src/vec/drain.rs b/library/alloc/src/vec/drain.rs
index 089cd4db64c..1bff19d05c1 100644
--- a/library/alloc/src/vec/drain.rs
+++ b/library/alloc/src/vec/drain.rs
@@ -128,10 +128,6 @@ impl<T, A: Allocator> Drop for Drain<'_, T, A> {
 
         let iter = mem::replace(&mut self.iter, (&mut []).iter());
         let drop_len = iter.len();
-        let drop_ptr = iter.as_slice().as_ptr();
-
-        // forget iter so there's no aliasing reference
-        drop(iter);
 
         let mut vec = self.vec;
 
@@ -155,6 +151,12 @@ impl<T, A: Allocator> Drop for Drain<'_, T, A> {
             return;
         }
 
+        // as_slice() must only be called when iter.len() is > 0 because
+        // vec::Splice modifies vec::Drain fields and may grow the vec which would invalidate
+        // the iterator's internal pointers. Creating a reference to deallocated memory
+        // is invalid even when it is zero-length
+        let drop_ptr = iter.as_slice().as_ptr();
+
         unsafe {
             // drop_ptr comes from a slice::Iter which only gives us a &[T] but for drop_in_place
             // a pointer with mutable provenance is necessary. Therefore we must reconstruct