about summary refs log tree commit diff
path: root/src/liballoc/collections
diff options
context:
space:
mode:
authorJonas Schievink <jonasschievink@gmail.com>2019-12-13 14:51:37 +0100
committerJonas Schievink <jonasschievink@gmail.com>2020-01-19 20:23:07 +0100
commita859ca5c87ddfaa635fb4cacf8a41e04fd9b02e8 (patch)
tree6f8e33d410f21eec6fafc586b6775af1c4fd0bc6 /src/liballoc/collections
parentc0e02ad724f05f73b957b3d6f6314a9a2e5c284e (diff)
downloadrust-a859ca5c87ddfaa635fb4cacf8a41e04fd9b02e8.tar.gz
rust-a859ca5c87ddfaa635fb4cacf8a41e04fd9b02e8.zip
Fix `binary_heap::DrainSorted` drop leak on panics
Diffstat (limited to 'src/liballoc/collections')
-rw-r--r--src/liballoc/collections/binary_heap.rs16
1 files changed, 14 insertions, 2 deletions
diff --git a/src/liballoc/collections/binary_heap.rs b/src/liballoc/collections/binary_heap.rs
index c527b378f74..f38fe997b73 100644
--- a/src/liballoc/collections/binary_heap.rs
+++ b/src/liballoc/collections/binary_heap.rs
@@ -147,7 +147,7 @@
 
 use core::fmt;
 use core::iter::{FromIterator, FusedIterator, TrustedLen};
-use core::mem::{size_of, swap, ManuallyDrop};
+use core::mem::{self, size_of, swap, ManuallyDrop};
 use core::ops::{Deref, DerefMut};
 use core::ptr;
 
@@ -1239,7 +1239,19 @@ pub struct DrainSorted<'a, T: Ord> {
 impl<'a, T: Ord> Drop for DrainSorted<'a, T> {
     /// Removes heap elements in heap order.
     fn drop(&mut self) {
-        while let Some(_) = self.inner.pop() {}
+        struct DropGuard<'r, 'a, T: Ord>(&'r mut DrainSorted<'a, T>);
+
+        impl<'r, 'a, T: Ord> Drop for DropGuard<'r, 'a, T> {
+            fn drop(&mut self) {
+                while let Some(_) = self.0.inner.pop() {}
+            }
+        }
+
+        while let Some(item) = self.inner.pop() {
+            let guard = DropGuard(self);
+            drop(item);
+            mem::forget(guard);
+        }
     }
 }