From bcf82efe081dd12e4b6708241f5a1d165d103cae Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 17 Nov 2018 14:51:45 +0100 Subject: [PATCH] deallocate locals before validation, to catch dangling references --- src/librustc_mir/interpret/eval_context.rs | 30 ++++++++++++++-------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index f9c28753c2dcf..148442deaad7e 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -492,7 +492,24 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc let frame = self.stack.pop().expect( "tried to pop a stack frame, but there were none", ); - // Validate the return value. + // Abort early if we do not want to clean up: We also avoid validation in that case, + // because this is CTFE and the final value will be thoroughly validated anyway. + match frame.return_to_block { + StackPopCleanup::Goto(_) => {}, + StackPopCleanup::None { cleanup } => { + if !cleanup { + assert!(self.stack.is_empty(), "only the topmost frame should ever be leaked"); + // Leak the locals, skip validation. + return Ok(()); + } + } + } + // Deallocate all locals that are backed by an allocation. + for local in frame.locals { + self.deallocate_local(local)?; + } + // Validate the return value. Do this after deallocating so that we catch dangling + // references. if let Some(return_place) = frame.return_place { if M::enforce_validity(self) { // Data got changed, better make sure it matches the type! @@ -518,16 +535,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc StackPopCleanup::Goto(block) => { self.goto_block(block)?; } - StackPopCleanup::None { cleanup } => { - if !cleanup { - // Leak the locals. - return Ok(()); - } - } - } - // Deallocate all locals that are backed by an allocation. - for local in frame.locals { - self.deallocate_local(local)?; + StackPopCleanup::None { .. } => {} } if self.stack.len() > 1 { // FIXME should be "> 0", printing topmost frame crashes rustc...