about summary refs log tree commit diff
path: root/src/liballoc/tests
diff options
context:
space:
mode:
authorJonas Schievink <jonasschievink@gmail.com>2019-12-13 17:54:26 +0100
committerJonas Schievink <jonasschievink@gmail.com>2020-01-19 20:23:41 +0100
commit5d04790dd2e73f3faf08d528e3675e131585ec01 (patch)
tree5aa4271596ae881762bf2d636979512a622a9b9a /src/liballoc/tests
parent3e5eb2634cbb356b626e028a4be1305d4a44a023 (diff)
downloadrust-5d04790dd2e73f3faf08d528e3675e131585ec01.tar.gz
rust-5d04790dd2e73f3faf08d528e3675e131585ec01.zip
Avoid leak in `vec::Drain` when item drop panics
Diffstat (limited to 'src/liballoc/tests')
-rw-r--r--src/liballoc/tests/vec.rs39
1 files changed, 39 insertions, 0 deletions
diff --git a/src/liballoc/tests/vec.rs b/src/liballoc/tests/vec.rs
index 2a9bfefc713..80acba0a3a1 100644
--- a/src/liballoc/tests/vec.rs
+++ b/src/liballoc/tests/vec.rs
@@ -1,6 +1,7 @@
 use std::borrow::Cow;
 use std::collections::TryReserveError::*;
 use std::mem::size_of;
+use std::panic::{catch_unwind, AssertUnwindSafe};
 use std::vec::{Drain, IntoIter};
 use std::{isize, usize};
 
@@ -586,6 +587,44 @@ fn test_drain_inclusive_out_of_bounds() {
 }
 
 #[test]
+fn test_drain_leak() {
+    static mut DROPS: i32 = 0;
+
+    #[derive(Debug, PartialEq)]
+    struct D(u32, bool);
+
+    impl Drop for D {
+        fn drop(&mut self) {
+            unsafe {
+                DROPS += 1;
+            }
+
+            if self.1 {
+                panic!("panic in `drop`");
+            }
+        }
+    }
+
+    let mut v = vec![
+        D(0, false),
+        D(1, false),
+        D(2, false),
+        D(3, false),
+        D(4, true),
+        D(5, false),
+        D(6, false),
+    ];
+
+    catch_unwind(AssertUnwindSafe(|| {
+        v.drain(2..=5);
+    }))
+    .ok();
+
+    assert_eq!(unsafe { DROPS }, 4);
+    assert_eq!(v, vec![D(0, false), D(1, false), D(6, false),]);
+}
+
+#[test]
 fn test_splice() {
     let mut v = vec![1, 2, 3, 4, 5];
     let a = [10, 11, 12];