fix: finally 体直落进入时置位 finally_active 防完成穿越计数错乱
catch 体正常结束后指令直落入 finally 体,此前 finally_active 未被置位, finally 内 break/continue/return/throw 触发未进入分支导致 finally 体重复 执行、完成计数错乱。新增无操作数标记指令 TRY_FINALLY_ENTER,在 finally 体入口统一置位栈顶 handler 的 finally_active,覆盖 JMP/直落/unwind/完成 穿越/挂起恢复全部进入路径,并删除 control_flow.rs 中对跳转目标匹配的 脆弱栈顶检测。
This commit is contained in:
@@ -9,13 +9,6 @@ impl Vm {
|
||||
pub(crate) fn dispatch_jmp(&mut self, instr: Instr) {
|
||||
let offset = opcode::offset16(instr) as isize;
|
||||
let target = ((self.pc as isize) + offset - 1) as usize;
|
||||
// try 体正常完成跳入 finally(`JMP finally_pc`):标记 handler 进入 finally 体,
|
||||
// 供 break/continue/return/异常判定覆盖语义。
|
||||
if let Some(h) = self.try_stack.last_mut() {
|
||||
if h.frame_depth == self.frames.len() && h.finally_pc == Some(target) {
|
||||
h.finally_active = true;
|
||||
}
|
||||
}
|
||||
vm_trace!("JMP offset={}", offset);
|
||||
self.pc = target;
|
||||
}
|
||||
|
||||
@@ -1811,6 +1811,10 @@ impl Vm {
|
||||
self.dispatch_try_finally_begin(instr);
|
||||
}
|
||||
|
||||
OpCode::TRY_FINALLY_ENTER => {
|
||||
self.dispatch_try_finally_enter();
|
||||
}
|
||||
|
||||
OpCode::TRY_FINALLY_END => match self.dispatch_try_finally_end() {
|
||||
Ok(Some(result)) => return Ok(result),
|
||||
Ok(None) => {}
|
||||
|
||||
@@ -495,6 +495,20 @@ impl Vm {
|
||||
});
|
||||
}
|
||||
|
||||
/// finally 体入口标记:置位栈顶 try handler 的 `finally_active`。
|
||||
///
|
||||
/// # 注意事项
|
||||
/// - 所有进入 finally 体的路径(try/catch 体 JMP、catch 体直落、异常 unwind、
|
||||
/// 完成穿越、生成器/async 恢复)都先执行本指令,统一完成置位,消除对跳转
|
||||
/// 目标匹配的依赖。栈顶在标记执行时必然是本 finally 的 handler。
|
||||
/// - 幂等:finally 体已置位(unwind/完成穿越路径先行置位)时重复置 true 无害。
|
||||
pub(crate) fn dispatch_try_finally_enter(&mut self) {
|
||||
vm_trace!("TRY_FINALLY_ENTER");
|
||||
if let Some(h) = self.try_stack.last_mut() {
|
||||
h.finally_active = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// finally 完成分发点:弹出当前 handler 后统一恢复在途异常或控制流完成。
|
||||
///
|
||||
/// # 步骤
|
||||
|
||||
Reference in New Issue
Block a user