Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 64044eb

Browse files
author
hyd-dev
committed
Check whether unwinding is allowed before popping the stack frame
1 parent ac39f36 commit 64044eb

File tree

1 file changed

+15
-16
lines changed

1 file changed

+15
-16
lines changed

compiler/rustc_mir/src/interpret/eval_context.rs

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -798,26 +798,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
798798
throw_ub_format!("unwinding past the topmost frame of the stack");
799799
}
800800

801-
let frame =
802-
self.stack_mut().pop().expect("tried to pop a stack frame, but there were none");
803-
804-
if !unwinding {
805-
// Copy the return value to the caller's stack frame.
806-
if let Some(ref return_place) = frame.return_place {
807-
let op = self.access_local(&frame, mir::RETURN_PLACE, None)?;
808-
self.copy_op_transmute(&op, return_place)?;
809-
trace!("{:?}", self.dump_place(**return_place));
810-
} else {
811-
throw_ub!(Unreachable);
812-
}
813-
}
814-
815-
// Now where do we jump next?
801+
// Where do we jump next?
816802

817803
// Usually we want to clean up (deallocate locals), but in a few rare cases we don't.
818804
// In that case, we return early. We also avoid validation in that case,
819805
// because this is CTFE and the final value will be thoroughly validated anyway.
820-
let (cleanup, next_block) = match (frame.return_to_block, unwinding) {
806+
let (cleanup, next_block) = match (self.frame().return_to_block, unwinding) {
821807
(StackPopCleanup::Goto { ret, .. }, false) => (true, Some(ret)),
822808
(StackPopCleanup::Goto { unwind, .. }, true) => (
823809
true,
@@ -832,6 +818,19 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
832818
(StackPopCleanup::None { cleanup, .. }, _) => (cleanup, None),
833819
};
834820

821+
let frame = self.stack_mut().pop().unwrap();
822+
823+
if !unwinding {
824+
// Copy the return value to the caller's stack frame.
825+
if let Some(ref return_place) = frame.return_place {
826+
let op = self.access_local(&frame, mir::RETURN_PLACE, None)?;
827+
self.copy_op_transmute(&op, return_place)?;
828+
trace!("{:?}", self.dump_place(**return_place));
829+
} else {
830+
throw_ub!(Unreachable);
831+
}
832+
}
833+
835834
if !cleanup {
836835
assert!(self.stack().is_empty(), "only the topmost frame should ever be leaked");
837836
assert!(next_block.is_none(), "tried to skip cleanup when we have a next block!");

0 commit comments

Comments
 (0)