From 1eadb5ac1bbae553830d48607b06a101c3f1c1a1 Mon Sep 17 00:00:00 2001 From: pjh456 <147148383@qq.com> Date: Wed, 12 Aug 2026 03:30:03 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20BigInt=20SUB/MUL=20=E9=99=A4=200n=20?= =?UTF-8?q?=E4=B8=8D=E5=86=8D=E8=AF=AF=E6=8A=9B=20Division=20by=20zero?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit binary_arith! 的 is_zero() 守卫无条件生效,x - 0n 与 x * 0n(含包装对象形式) 误抛 RangeError。仅 DIV/MOD 应拒绝 BigInt 零除数,SUB/MUL 正常计算。 test262 language/expressions/subtraction 由 29/6 通过提升到 30/5。 --- crates/oxide_vm/src/vm.rs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/crates/oxide_vm/src/vm.rs b/crates/oxide_vm/src/vm.rs index e9875e5c..8b5aad48 100644 --- a/crates/oxide_vm/src/vm.rs +++ b/crates/oxide_vm/src/vm.rs @@ -80,7 +80,7 @@ macro_rules! throw_err { } macro_rules! binary_arith { - ($self:ident, $a:expr, $b:expr, $rd:expr, $op:tt) => {{ + ($self:ident, $a:expr, $b:expr, $rd:expr, $op:tt, $check_zero:expr) => {{ let lv = $self.regs[$a]; let rv = $self.regs[$b]; if lv.is_int() && rv.is_int() { @@ -88,8 +88,9 @@ macro_rules! binary_arith { } else if lv.is_bigint() && rv.is_bigint() { let l = $self.bigint_value(lv).clone(); let r = $self.bigint_value(rv).clone(); - if r.is_zero() { - // BigInt 除/模零:规范要求 RangeError(Number 路径走 f64 inf/NaN)。 + if r.is_zero() && $check_zero { + // 仅除/模对 BigInt 零除数抛 RangeError;SUB/MUL 等其余二元运算 + // 遇到 0n 必须正常计算(Number 路径走 f64 inf/NaN)。 $self.raise_error_kind("RangeError", "Division by zero")?; $self.regs[$rd] = JsValue::undefined(); } else { @@ -104,7 +105,7 @@ macro_rules! binary_arith { // 包装对象 coerce 后暴露双 BigInt(如 Object(2n) / 2n)。 let lv = $self.bigint_value(l).clone(); let rv = $self.bigint_value(r).clone(); - if rv.is_zero() { + if rv.is_zero() && $check_zero { $self.raise_error_kind("RangeError", "Division by zero")?; $self.regs[$rd] = JsValue::undefined(); } else { @@ -1254,19 +1255,19 @@ impl Vm { } OpCode::SUB => { - binary_arith!(self, a, b, rd, -); + binary_arith!(self, a, b, rd, -, false); } OpCode::MUL => { - binary_arith!(self, a, b, rd, *); + binary_arith!(self, a, b, rd, *, false); } OpCode::DIV => { - binary_arith!(self, a, b, rd, /); + binary_arith!(self, a, b, rd, /, true); } OpCode::MOD => { - binary_arith!(self, a, b, rd, %); + binary_arith!(self, a, b, rd, %, true); } OpCode::NEG => {