diff options
| author | hyd-dev <yd-huang@outlook.com> | 2021-05-25 00:08:26 +0800 |
|---|---|---|
| committer | hyd-dev <yd-huang@outlook.com> | 2021-05-25 03:42:25 +0800 |
| commit | 64044eb2371d955c2e854f849eaccb45dbd33c4a (patch) | |
| tree | 408f6b6103ec5a0debe272213e3c315b3a1a43f2 | |
| parent | ac39f365266fcbfaf8d1fb31ac59feba60950e92 (diff) | |
| download | rust-64044eb2371d955c2e854f849eaccb45dbd33c4a.tar.gz rust-64044eb2371d955c2e854f849eaccb45dbd33c4a.zip | |
Check whether unwinding is allowed before popping the stack frame
| -rw-r--r-- | compiler/rustc_mir/src/interpret/eval_context.rs | 31 |
1 files changed, 15 insertions, 16 deletions
diff --git a/compiler/rustc_mir/src/interpret/eval_context.rs b/compiler/rustc_mir/src/interpret/eval_context.rs index f1ba669492f..bb894e5ce0b 100644 --- a/compiler/rustc_mir/src/interpret/eval_context.rs +++ b/compiler/rustc_mir/src/interpret/eval_context.rs @@ -798,26 +798,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { throw_ub_format!("unwinding past the topmost frame of the stack"); } - let frame = - self.stack_mut().pop().expect("tried to pop a stack frame, but there were none"); - - if !unwinding { - // Copy the return value to the caller's stack frame. - if let Some(ref return_place) = frame.return_place { - let op = self.access_local(&frame, mir::RETURN_PLACE, None)?; - self.copy_op_transmute(&op, return_place)?; - trace!("{:?}", self.dump_place(**return_place)); - } else { - throw_ub!(Unreachable); - } - } - - // Now where do we jump next? + // Where do we jump next? // Usually we want to clean up (deallocate locals), but in a few rare cases we don't. // In that case, we return early. We also avoid validation in that case, // because this is CTFE and the final value will be thoroughly validated anyway. - let (cleanup, next_block) = match (frame.return_to_block, unwinding) { + let (cleanup, next_block) = match (self.frame().return_to_block, unwinding) { (StackPopCleanup::Goto { ret, .. }, false) => (true, Some(ret)), (StackPopCleanup::Goto { unwind, .. }, true) => ( true, @@ -832,6 +818,19 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { (StackPopCleanup::None { cleanup, .. }, _) => (cleanup, None), }; + let frame = self.stack_mut().pop().unwrap(); + + if !unwinding { + // Copy the return value to the caller's stack frame. + if let Some(ref return_place) = frame.return_place { + let op = self.access_local(&frame, mir::RETURN_PLACE, None)?; + self.copy_op_transmute(&op, return_place)?; + trace!("{:?}", self.dump_place(**return_place)); + } else { + throw_ub!(Unreachable); + } + } + if !cleanup { assert!(self.stack().is_empty(), "only the topmost frame should ever be leaked"); assert!(next_block.is_none(), "tried to skip cleanup when we have a next block!"); |
