about summary refs log tree commit diff
path: root/src/liballoc/tests
diff options
context:
space:
mode:
authorJonas Schievink <jonasschievink@gmail.com>2019-12-14 00:55:06 +0100
committerJonas Schievink <jonasschievink@gmail.com>2020-01-19 20:24:36 +0100
commit0ae16b47ffee866ee49f909ea213a28d8068cf56 (patch)
treebbc88dd073366bc4f1cab9f88f3aec0ce4c2430e /src/liballoc/tests
parent163ed23f0081d7283ccaef39141bc29879260663 (diff)
downloadrust-0ae16b47ffee866ee49f909ea213a28d8068cf56.tar.gz
rust-0ae16b47ffee866ee49f909ea213a28d8068cf56.zip
Avoid leak in DrainFilter when a drop panics
Diffstat (limited to 'src/liballoc/tests')
-rw-r--r--src/liballoc/tests/linked_list.rs36
1 files changed, 35 insertions, 1 deletions
diff --git a/src/liballoc/tests/linked_list.rs b/src/liballoc/tests/linked_list.rs
index b7736515b26..aa3f582a165 100644
--- a/src/liballoc/tests/linked_list.rs
+++ b/src/liballoc/tests/linked_list.rs
@@ -1,5 +1,5 @@
 use std::collections::LinkedList;
-use std::panic::catch_unwind;
+use std::panic::{catch_unwind, AssertUnwindSafe};
 
 #[test]
 fn test_basic() {
@@ -532,6 +532,40 @@ fn drain_filter_complex() {
 }
 
 #[test]
+fn drain_filter_drop_panic_leak() {
+    static mut DROPS: i32 = 0;
+
+    struct D(bool);
+
+    impl Drop for D {
+        fn drop(&mut self) {
+            unsafe {
+                DROPS += 1;
+            }
+
+            if self.0 {
+                panic!("panic in `drop`");
+            }
+        }
+    }
+
+    let mut q = LinkedList::new();
+    q.push_back(D(false));
+    q.push_back(D(false));
+    q.push_back(D(false));
+    q.push_back(D(false));
+    q.push_back(D(false));
+    q.push_front(D(false));
+    q.push_front(D(true));
+    q.push_front(D(false));
+
+    catch_unwind(AssertUnwindSafe(|| drop(q.drain_filter(|_| true)))).ok();
+
+    assert_eq!(unsafe { DROPS }, 8);
+    assert!(q.is_empty());
+}
+
+#[test]
 fn test_drop() {
     static mut DROPS: i32 = 0;
     struct Elem;