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 18:36:35 +0100
committerJonas Schievink <jonasschievink@gmail.com>2020-01-19 20:24:08 +0100
commitdc492452dae29d75b14afe3559f5fb59be7f2d3a (patch)
tree3005b81d064c2a8bb8af93ac2cad49e126484292 /src/liballoc/collections
parent5d04790dd2e73f3faf08d528e3675e131585ec01 (diff)
downloadrust-dc492452dae29d75b14afe3559f5fb59be7f2d3a.tar.gz
rust-dc492452dae29d75b14afe3559f5fb59be7f2d3a.zip
Fix leak in btree_map::IntoIter when drop panics
Diffstat (limited to 'src/liballoc/collections')
-rw-r--r--src/liballoc/collections/btree/map.rs17
1 files changed, 16 insertions, 1 deletions
diff --git a/src/liballoc/collections/btree/map.rs b/src/liballoc/collections/btree/map.rs
index 302c2bcd5e4..71ddfc4ef63 100644
--- a/src/liballoc/collections/btree/map.rs
+++ b/src/liballoc/collections/btree/map.rs
@@ -1381,7 +1381,22 @@ impl<K, V> IntoIterator for BTreeMap<K, V> {
 #[stable(feature = "btree_drop", since = "1.7.0")]
 impl<K, V> Drop for IntoIter<K, V> {
     fn drop(&mut self) {
-        self.for_each(drop);
+        struct DropGuard<'a, K, V>(&'a mut IntoIter<K, V>);
+
+        impl<'a, K, V> Drop for DropGuard<'a, K, V> {
+            fn drop(&mut self) {
+                // Continue the same loop we perform below. This only runs when unwinding, so we
+                // don't have to care about panics this time (they'll abort).
+                while let Some(_) = self.0.next() {}
+            }
+        }
+
+        while let Some(pair) = self.next() {
+            let guard = DropGuard(self);
+            drop(pair);
+            mem::forget(guard);
+        }
+
         unsafe {
             let leaf_node = ptr::read(&self.front).into_node();
             if leaf_node.is_shared_root() {