diff options
| author | Jonas Schievink <jonasschievink@gmail.com> | 2019-12-13 16:41:19 +0100 |
|---|---|---|
| committer | Jonas Schievink <jonasschievink@gmail.com> | 2020-01-19 20:23:07 +0100 |
| commit | 3e5eb2634cbb356b626e028a4be1305d4a44a023 (patch) | |
| tree | 8154f8e4fd2506207f18ea5db0d57fda185a2305 /src/liballoc/collections | |
| parent | a859ca5c87ddfaa635fb4cacf8a41e04fd9b02e8 (diff) | |
| download | rust-3e5eb2634cbb356b626e028a4be1305d4a44a023.tar.gz rust-3e5eb2634cbb356b626e028a4be1305d4a44a023.zip | |
Fix `VecDeque::truncate` leak on drop panic
Diffstat (limited to 'src/liballoc/collections')
| -rw-r--r-- | src/liballoc/collections/vec_deque.rs | 17 |
1 files changed, 16 insertions, 1 deletions
diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index 2cc450bb68a..7307aad8a9e 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -866,6 +866,18 @@ impl<T> VecDeque<T> { /// ``` #[stable(feature = "deque_extras", since = "1.16.0")] pub fn truncate(&mut self, len: usize) { + /// Runs the destructor for all items in the slice when it gets dropped (normally or + /// during unwinding). + struct Dropper<'a, T>(&'a mut [T]); + + impl<'a, T> Drop for Dropper<'a, T> { + fn drop(&mut self) { + unsafe { + ptr::drop_in_place(self.0); + } + } + } + // Safe because: // // * Any slice passed to `drop_in_place` is valid; the second case has @@ -888,8 +900,11 @@ impl<T> VecDeque<T> { let drop_back = back as *mut _; let drop_front = front.get_unchecked_mut(len..) as *mut _; self.head = self.wrap_sub(self.head, num_dropped); + + // Make sure the second half is dropped even when a destructor + // in the first one panics. + let _back_dropper = Dropper(&mut *drop_back); ptr::drop_in_place(drop_front); - ptr::drop_in_place(drop_back); } } } |
