From 0ae16b47ffee866ee49f909ea213a28d8068cf56 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sat, 14 Dec 2019 00:55:06 +0100 Subject: Avoid leak in DrainFilter when a drop panics --- src/liballoc/tests/linked_list.rs | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) (limited to 'src/liballoc/tests') 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() { @@ -531,6 +531,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; -- cgit 1.4.1-3-g733a5