Skip to content

Commit

Permalink
Rollup merge of #67235 - jonas-schievink:vecdeque-leak, r=KodrAus
Browse files Browse the repository at this point in the history
VecDeque: drop remaining items on destructor panic

Closes #67232
  • Loading branch information
Centril authored Dec 13, 2019
2 parents df9e491 + 82c09b7 commit 48164f8
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 1 deletion.
14 changes: 13 additions & 1 deletion src/liballoc/collections/vec_deque.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,11 +144,23 @@ impl<T: Clone> Clone for VecDeque<T> {
#[stable(feature = "rust1", since = "1.0.0")]
unsafe impl<#[may_dangle] T> Drop for VecDeque<T> {
fn drop(&mut self) {
/// Runs the destructor for all items in the slice when it gets dropped (normally or
/// during unwinding).
struct Dropper<'a, T>(&'a mut [T]);

impl<'a, T> Drop for Dropper<'a, T> {
fn drop(&mut self) {
unsafe {
ptr::drop_in_place(self.0);
}
}
}

let (front, back) = self.as_mut_slices();
unsafe {
let _back_dropper = Dropper(back);
// use drop for [T]
ptr::drop_in_place(front);
ptr::drop_in_place(back);
}
// RawVec handles deallocation
}
Expand Down
34 changes: 34 additions & 0 deletions src/liballoc/tests/vec_deque.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::collections::TryReserveError::*;
use std::collections::{vec_deque::Drain, VecDeque};
use std::fmt::Debug;
use std::mem::size_of;
use std::panic::catch_unwind;
use std::{isize, usize};

use crate::hash;
Expand Down Expand Up @@ -709,6 +710,39 @@ fn test_drop_clear() {
assert_eq!(unsafe { DROPS }, 4);
}

#[test]
fn test_drop_panic() {
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 = VecDeque::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(false));
q.push_front(D(true));

catch_unwind(move || drop(q)).ok();

assert_eq!(unsafe { DROPS }, 8);
}

#[test]
fn test_reserve_grow() {
// test growth path A
Expand Down

0 comments on commit 48164f8

Please sign in to comment.