fix: 控制流逃出计数读越界防御,无 ext 字的返回安全降级

This commit is contained in:
2026-08-16 15:02:04 +08:00
parent 6d4a91643c
commit 7e180d9ac1
2 changed files with 9 additions and 5 deletions
+7
View File
@@ -350,7 +350,14 @@ impl Vm {
/// 读取 BREAK/CONTINUE/RETURN 的 ext 字逃出计数(低 16 位 for-of,高 16 位
/// for-in)。调用时机:主循环已把 pc 推进到 ext 字位置;两条跳转/返回路径
/// 都会覆盖 pc,此处无需再推进。
///
/// # 边界与前提
/// - 手工构造的 IR 可能让 RETURN/BREAK/CONTINUE 落在末位且无 ext 字(pc == len),
/// 此时按 (0, 0) 处理:无迭代器逃出,语义正确。
fn read_escape_counts(&self) -> (usize, usize) {
if self.pc >= self.bytecode.len() {
return (0, 0);
}
let packed = self.bytecode[self.pc];
((packed & 0xFFFF) as usize, (packed >> 16) as usize)
}
+2 -5
View File
@@ -62,10 +62,7 @@ fn spill_unspill_roundtrip() {
#[test]
fn frame_boundary_parent_spill_survives_call() {
let child = int_module(
vec![
Inst::load_const(Operand::Reg(3), 0),
Inst::new(OpCode::RETURN, Operand::Reg(3), Operand::None, Operand::None),
],
vec![Inst::load_const(Operand::Reg(3), 0), Inst::ret(Operand::Reg(3), 0, 0)],
99,
4,
Vec::new(),
@@ -90,7 +87,7 @@ fn nested_call_both_spill() {
vec![
Inst::load_const(Operand::Reg(3), 0),
Inst::inst_spill(Operand::Reg(3), 0),
Inst::new(OpCode::RETURN, Operand::Reg(3), Operand::None, Operand::None),
Inst::ret(Operand::Reg(3), 0, 0),
],
99,
4,