From 5d04790dd2e73f3faf08d528e3675e131585ec01 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Fri, 13 Dec 2019 17:54:26 +0100 Subject: Avoid leak in `vec::Drain` when item drop panics --- src/liballoc/tests/vec.rs | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'src/liballoc/tests') 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}; @@ -585,6 +586,44 @@ fn test_drain_inclusive_out_of_bounds() { v.drain(5..=5); } +#[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]; -- cgit 1.4.1-3-g733a5