look past the next drop for the drop panic target

The previous code would leak data on a drop panic if the immediate next
drop was a StorageDead that was followed by another drop.
This commit is contained in:
Ariel Ben-Yehuda 2017-10-17 21:37:18 +03:00
parent a151d37401
commit a6ca84a383
2 changed files with 24 additions and 14 deletions

View file

@ -836,24 +836,22 @@ fn build_scope_drops<'tcx>(cfg: &mut CFG<'tcx>,
generator_drop: bool)
-> BlockAnd<()> {
debug!("build_scope_drops({:?} -> {:?})", block, scope);
let mut iter = scope.drops.iter().rev().peekable();
let mut iter = scope.drops.iter().rev();
while let Some(drop_data) = iter.next() {
let source_info = scope.source_info(drop_data.span);
match drop_data.kind {
DropKind::Value { .. } => {
// Try to find the next block with its cached block
// for us to diverge into in case the drop panics.
let on_diverge = iter.peek().iter().filter_map(|dd| {
let on_diverge = iter.clone().filter_map(|dd| {
match dd.kind {
DropKind::Value { cached_block } => {
let result = cached_block.get(generator_drop);
if result.is_none() {
span_bug!(drop_data.span, "cached block not present?")
}
result
},
DropKind::Value { cached_block } => Some(cached_block),
DropKind::Storage => None
}
}).map(|cached_block| {
cached_block
.get(generator_drop)
.unwrap_or_else(|| span_bug!(drop_data.span, "cached block not present?"))
}).next();
// If theres no `cached_block`s within current scope,
// we must look for one in the enclosing scope.

View file

@ -177,6 +177,17 @@ fn generator(a: &Allocator, run_count: usize) {
}
}
fn mixed_drop_and_nondrop(a: &Allocator) {
// check that destructor panics handle drop
// and non-drop blocks in the same scope correctly.
//
// Surprisingly enough, this used to not work.
let (x, y, z);
x = a.alloc();
y = 5;
z = a.alloc();
}
#[allow(unreachable_code)]
fn vec_unreachable(a: &Allocator) {
let _x = vec![a.alloc(), a.alloc(), a.alloc(), return];
@ -244,11 +255,12 @@ fn main() {
run_test(|a| field_assignment(a, false));
run_test(|a| field_assignment(a, true));
// FIXME: fix leaks on panics
run_test_nopanic(|a| generator(a, 0));
run_test_nopanic(|a| generator(a, 1));
run_test_nopanic(|a| generator(a, 2));
run_test_nopanic(|a| generator(a, 3));
run_test(|a| generator(a, 0));
run_test(|a| generator(a, 1));
run_test(|a| generator(a, 2));
run_test(|a| generator(a, 3));
run_test(|a| mixed_drop_and_nondrop(a));
run_test_nopanic(|a| union1(a));
}