about summary refs log tree commit diff
diff options
context:
space:
mode:
authorThe 8472 <git@infinite-source.de>2021-12-11 17:10:56 +0100
committerThe 8472 <git@infinite-source.de>2021-12-11 17:10:56 +0100
commit9063b64cff102c63f542452fa23d414c75a25ba7 (patch)
treec1d94b34bc5ba00cb89c36301bc5c8998d764d01
parent4a66a704b2c3d30ff07d89380ebb9ba3de3b3182 (diff)
downloadrust-9063b64cff102c63f542452fa23d414c75a25ba7.tar.gz
rust-9063b64cff102c63f542452fa23d414c75a25ba7.zip
Fix zero-sized reference to deallocated memory
fixes #91772
-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