about summary refs log tree commit diff
path: root/library/alloc/src/vec
diff options
context:
space:
mode:
authorThe 8472 <git@infinite-source.de>2023-04-29 12:34:28 +0200
committerThe 8472 <git@infinite-source.de>2023-09-03 19:59:47 +0200
commit6e4f98c987f196ed27a3eae9ebb019ec89759f6c (patch)
treeeb5d54ba0779de07257087cfb718ee311690859e /library/alloc/src/vec
parent3ca6bb0b44c3e65dab07e12aec9efb277dc206f9 (diff)
downloadrust-6e4f98c987f196ed27a3eae9ebb019ec89759f6c.tar.gz
rust-6e4f98c987f196ed27a3eae9ebb019ec89759f6c.zip
don't leak items if alloc::shrink panics
Diffstat (limited to 'library/alloc/src/vec')
-rw-r--r--library/alloc/src/vec/in_place_collect.rs8
1 files changed, 6 insertions, 2 deletions
diff --git a/library/alloc/src/vec/in_place_collect.rs b/library/alloc/src/vec/in_place_collect.rs
index d174074902a..20ecc50c4b6 100644
--- a/library/alloc/src/vec/in_place_collect.rs
+++ b/library/alloc/src/vec/in_place_collect.rs
@@ -225,16 +225,18 @@ where
         }
 
         // The ownership of the allocation and the new `T` values is temporarily moved into `dst_guard`.
-        // This is safe because `forget_allocation_drop_remaining` immediately forgets the allocation
+        // This is safe because
+        // * `forget_allocation_drop_remaining` immediately forgets the allocation
         // before any panic can occur in order to avoid any double free, and then proceeds to drop
         // any remaining values at the tail of the source.
+        // * the shrink either panics without invalidating the allocation, aborts or
+        //   succeeds. In the last case we disarm the guard.
         //
         // Note: This access to the source wouldn't be allowed by the TrustedRandomIteratorNoCoerce
         // contract (used by SpecInPlaceCollect below). But see the "O(1) collect" section in the
         // module documentation why this is ok anyway.
         let dst_guard = InPlaceDstBufDrop { ptr: dst_buf, len, cap: dst_cap };
         src.forget_allocation_drop_remaining();
-        mem::forget(dst_guard);
 
         // Adjust the allocation size if the source had a capacity in bytes that wasn't a multiple
         // of the destination type size.
@@ -256,6 +258,8 @@ where
             }
         }
 
+        mem::forget(dst_guard);
+
         let vec = unsafe { Vec::from_raw_parts(dst_buf, len, dst_cap) };
 
         vec