Firefox · SpiderMonkey
CVE-2026-109749
Logic Error in SpiderMonkey
Overview
Moderate
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Files Changed
js/src/jit/MacroAssembler.cppjs/src/jit/MacroAssembler.hjs/src/jit/arm/CodeGenerator-arm.cppjs/src/jit/arm/MacroAssembler-arm.cppjs/src/jit/arm/MacroAssembler-arm.hjs/src/jit/arm64/MacroAssembler-arm64.cppjs/src/jit/arm64/MacroAssembler-arm64.hjs/src/jit/loong64/MacroAssembler-loong64.cppjs/src/jit/loong64/MacroAssembler-loong64.hjs/src/jit/mips-shared/MacroAssembler-mips-shared.cppjs/src/jit/mips64/MacroAssembler-mips64.cppjs/src/jit/riscv64/MacroAssembler-riscv64.cppjs/src/jit/riscv64/MacroAssembler-riscv64.hjs/src/jit/wasm32/MacroAssembler-wasm32.cppjs/src/jit/x64/MacroAssembler-x64.cppjs/src/jit/x86-shared/MacroAssembler-x86-shared.cppjs/src/jit/x86-shared/MacroAssembler-x86-shared.hjs/src/jit/x86/CodeGenerator-x86.cppjs/src/jit/x86/MacroAssembler-x86.cppjs/src/wasm/WasmBCMemory.cppjs/src/wasm/WasmBaselineCompile.cpp
Patch
diff --git a/js/src/jit/MacroAssembler.cpp b/js/src/jit/MacroAssembler.cpp
index 109cd6d1bbf..44f057cd3b8 100644
--- a/js/src/jit/MacroAssembler.cpp
+++ b/js/src/jit/MacroAssembler.cpp
@@ -7278,7 +7278,7 @@ void MacroAssembler::wasmReturnCallRef(
append(wasm::CodeRangeUnwindInfo::Normal, currentOffset());
}
-void MacroAssembler::wasmBoundsCheckRange32(
+FaultingCodeRange MacroAssembler::wasmBoundsCheckRange32(
Register index, Register length, Register limit, Register tmp,
const wasm::TrapSiteDesc& trapSiteDesc) {
Label ok;
@@ -7290,9 +7290,10 @@ void MacroAssembler::wasmBoundsCheckRange32(
jump(&ok);
bind(&fail);
- wasmTrap(wasm::Trap::OutOfBounds, trapSiteDesc);
+ FaultingCodeRange fcr = wasmTrap(wasm::Trap::OutOfBounds, trapSiteDesc);
bind(&ok);
+ return fcr;
}
void MacroAssembler::wasmClampTable64Address(Register64 address, Register out) {
diff --git a/js/src/jit/MacroAssembler.h b/js/src/jit/MacroAssembler.h
index cdb9fcadf58..73096c29751 100644
--- a/js/src/jit/MacroAssembler.h
+++ b/js/src/jit/MacroAssembler.h
@@ -3845,14 +3845,24 @@ class MacroAssembler : public MacroAssemblerSpecific {
Address boundsCheckLimit, Label* label) PER_ARCH;
// Each wasm load/store instruction appends its own wasm::Trap::OutOfBounds.
- void wasmLoad(const wasm::MemoryAccessDesc& access, Operand srcAddr,
- AnyRegister out) DEFINED_ON(x86, x64);
- void wasmLoadI64(const wasm::MemoryAccessDesc& access, Operand srcAddr,
- Register64 out) DEFINED_ON(x86, x64);
- void wasmStore(const wasm::MemoryAccessDesc& access, AnyRegister value,
- Operand dstAddr) DEFINED_ON(x86, x64);
- void wasmStoreI64(const wasm::MemoryAccessDesc& access, Register64 value,
- Operand dstAddr) DEFINED_ON(x86);
+ FaultingCodeRange wasmLoad(const wasm::MemoryAccessDesc& access,
+ Operand srcAddr, AnyRegister out)
+ DEFINED_ON(x86, x64);
+
+ FaultingCodeRange wasmLoadI64(const wasm::MemoryAccessDesc& access,
+ Operand srcAddr, Register64 out)
+ DEFINED_ON(x64);
+ FaultingCodeRangePair wasmLoadI32x2(const wasm::MemoryAccessDesc& access,
+ Operand srcAddr, Register64 out)
+ DEFINED_ON(x86);
+
+ FaultingCodeRange wasmStore(const wasm::MemoryAccessDesc& access,
+ AnyRegister value, Operand dstAddr)
+ DEFINED_ON(x86, x64);
+
+ FaultingCodeRangePair wasmStoreI32x2(const wasm::MemoryAccessDesc& access,
+ Register64 value, Operand dstAddr)
+ DEFINED_ON(x86);
// For all the ARM/MIPS/LOONG64 wasmLoad and wasmStore functions below, `ptr`
// MUST equal `ptrScratch`, and that register will be updated based on
@@ -3860,47 +3870,72 @@ class MacroAssembler : public MacroAssemblerSpecific {
// `ptr` will be updated if access.offset32() != 0 or access.type() ==
// Scalar::Int64.
- void wasmLoad(const wasm::MemoryAccessDesc& access, Register memoryBase,
- Register ptr, Register ptrScratch, AnyRegister output)
+ FaultingCodeRange wasmLoad(const wasm::MemoryAccessDesc& access,
+ Register memoryBase, Register ptr,
+ Register ptrScratch, AnyRegister output)
DEFINED_ON(arm, loong64, mips64);
- void wasmLoadI64(const wasm::MemoryAccessDesc& access, Register memoryBase,
- Register ptr, Register ptrScratch, Register64 output)
- DEFINED_ON(arm, mips64, loong64);
- void wasmStore(const wasm::MemoryAccessDesc& access, AnyRegister value,
- Register memoryBase, Register ptr, Register ptrScratch)
+
+ FaultingCodeRangePair wasmLoadI32x2(const wasm::MemoryAccessDesc& access,
+ Register memoryBase, Register ptr,
+ Register ptrScratch, Register64 output)
+ DEFINED_ON(arm);
+ FaultingCodeRange wasmLoadI64(const wasm::MemoryAccessDesc& access,
+ Register memoryBase, Register ptr,
+ Register ptrScratch, Register64 output)
+ DEFINED_ON(mips64, loong64);
+
+ FaultingCodeRange wasmStore(const wasm::MemoryAccessDesc& access,
+ AnyRegister value, Register memoryBase,
+ Register ptr, Register ptrScratch)
DEFINED_ON(arm, loong64, mips64);
- void wasmStoreI64(const wasm::MemoryAccessDesc& access, Register64 value,
- Register memoryBase, Register ptr, Register ptrScratch)
- DEFINED_ON(arm, mips64, loong64);
+
+ FaultingCodeRangePair wasmStoreI32x2(const wasm::MemoryAccessDesc& access,
+ Register64 value, Register memoryBase,
+ Register ptr, Register ptrScratch)
+ DEFINED_ON(arm);
+ FaultingCodeRange wasmStoreI64(const wasm::MemoryAccessDesc& access,
+ Register64 value, Register memoryBase,
+ Register ptr, Register ptrScratch)
+ DEFINED_ON(mips64, loong64);
// These accept general memoryBase + ptr + offset (in `access`); the offset is
// always smaller than the guard region. They will insert an additional add
// if the offset is nonzero, and of course that add may require a temporary
// register for the offset if the offset is large, and instructions to set it
// up.
- void wasmLoad(const wasm::MemoryAccessDesc& access, Register memoryBase,
- Register ptr, AnyRegister output) DEFINED_ON(arm64);
- void wasmLoadI64(const wasm::MemoryAccessDesc& access, Register memoryBase,
- Register ptr, Register64 output) DEFINED_ON(arm64);
- void wasmStore(const wasm::MemoryAccessDesc& access, AnyRegister value,
- Register memoryBase, Register ptr) DEFINED_ON(arm64);
- void wasmStoreI64(const wasm::MemoryAccessDesc& access, Register64 value,
- Register memoryBase, Register ptr) DEFINED_ON(arm64);
+ FaultingCodeRange wasmLoad(const wasm::MemoryAccessDesc& access,
+ Register memoryBase, Register ptr,
+ AnyRegister output) DEFINED_ON(arm64);
+ FaultingCodeRange wasmLoadI64(const wasm::MemoryAccessDesc& access,
+ Register memoryBase, Register ptr,
+ Register64 output) DEFINED_ON(arm64);
+ FaultingCodeRange wasmStore(const wasm::MemoryAccessDesc& access,
+ AnyRegister value, Register memoryBase,
+ Register ptr) DEFINED_ON(arm64);
+ FaultingCodeRange wasmStoreI64(const wasm::MemoryAccessDesc& access,
+ Register64 value, Register memoryBase,
+ Register ptr) DEFINED_ON(arm64);
// RISCV64 additionally supports ZeroExtendIndex. The other parameters are the
// same as for ARM64.
- void wasmLoad(const wasm::MemoryAccessDesc& access, Register memoryBase,
- Register ptr, AnyRegister output,
- wasm::ZeroExtendIndex zeroExtend) DEFINED_ON(riscv64);
- void wasmLoadI64(const wasm::MemoryAccessDesc& access, Register memoryBase,
- Register ptr, Register64 output,
- wasm::ZeroExtendIndex zeroExtend) DEFINED_ON(riscv64);
- void wasmStore(const wasm::MemoryAccessDesc& access, AnyRegister value,
- Register memoryBase, Register ptr,
- wasm::ZeroExtendIndex zeroExtend) DEFINED_ON(riscv64);
- void wasmStoreI64(const wasm::MemoryAccessDesc& access, Register64 value,
- Register memoryBase, Register ptr,
- wasm::ZeroExtendIndex zeroExtend) DEFINED_ON(riscv64);
+ FaultingCodeRange wasmLoad(const wasm::MemoryAccessDesc& access,
+ Register memoryBase, Register ptr,
+ AnyRegister output,
+ wasm::ZeroExtendIndex zeroExtend)
+ DEFINED_ON(riscv64);
+ FaultingCodeRange wasmLoadI64(const wasm::MemoryAccessDesc& access,
+ Register memoryBase, Register ptr,
+ Register64 output,
+ wasm::ZeroExtendIndex zeroExtend)
+ DEFINED_ON(riscv64);
+ FaultingCodeRange wasmStore(const wasm::MemoryAccessDesc& access,
+ AnyRegister value, Register memoryBase,
+ Register ptr, wasm::ZeroExtendIndex zeroExtend)
+ DEFINED_ON(riscv64);
+ FaultingCodeRange wasmStoreI64(const wasm::MemoryAccessDesc& access,
+ Register64 value, Register memoryBase,
+ Register ptr, wasm::ZeroExtendIndex zeroExtend)
+ DEFINED_ON(riscv64);
// `ptr` will always be updated.
void wasmUnalignedLoad(const wasm::MemoryAccessDesc& access,
@@ -4094,9 +4129,9 @@ class MacroAssembler : public MacroAssemblerSpecific {
// itself being out of bounds.
//
// `length` and `limit` will be unchanged.
- void wasmBoundsCheckRange32(Register index, Register length, Register limit,
- Register tmp,
- const wasm::TrapSiteDesc& trapSiteDesc);
+ FaultingCodeRange wasmBoundsCheckRange32(
+ Register index, Register length, Register limit, Register tmp,
+ const wasm::TrapSiteDesc& trapSiteDesc);
// Returns information about which registers are necessary for a
// branchWasmRefIsSubtype call.
@@ -4574,84 +4609,95 @@ class MacroAssembler : public MacroAssemblerSpecific {
// Constraints, when omitted, are exactly as for the primitive operations
// above.
- void wasmCompareExchange(const wasm::MemoryAccessDesc& access,
- const Address& mem, Register expected,
- Register replacement, Register output)
+ FaultingCodeRange wasmCompareExchange(const wasm::MemoryAccessDesc& access,
+ const Address& mem, Register expected,
+ Register replacement, Register output)
DEFINED_ON(arm, arm64, x86_shared);
- void wasmCompareExchange(const wasm::MemoryAccessDesc& access,
- const BaseIndex& mem, Register expected,
- Register replacement, Register output)
+ FaultingCodeRange wasmCompareExchange(const wasm::MemoryAccessDesc& access,
+ const BaseIndex& mem, Register expected,
+ Register replacement, Register output)
DEFINED_ON(arm, arm64, x86_shared);
- void wasmCompareExchange(const wasm::MemoryAccessDesc& access,
- const Address& mem, Register expected,
- Register replacement, Register valueTemp,
- Register offsetTemp, Register maskTemp,
- Register output)
+ FaultingCodeRange wasmCompareExchange(const wasm::MemoryAccessDesc& access,
+ const Address& mem, Register expected,
+ Register replacement,
+ Register valueTemp, Register offsetTemp,
+ Register maskTemp, Register output)
DEFINED_ON(mips64, loong64, riscv64);
- void wasmCompareExchange(const wasm::MemoryAccessDesc& access,
- const BaseIndex& mem, Register expected,
- Register replacement, Register valueTemp,
- Register offsetTemp, Register maskTemp,
- Register output)
+ FaultingCodeRange wasmCompareExchange(const wasm::MemoryAccessDesc& access,
+ const BaseIndex& mem, Register expected,
+ Register replacement,
+ Register valueTemp, Register offsetTemp,
+ Register maskTemp, Register output)
DEFINED_ON(mips64, loong64, riscv64);
- void wasmCompareExchange(const wasm::MemoryAccessDesc& access,
- const BaseIndex& mem, Register expected,
- Register replacement, Register valueTemp,
- Register offsetTemp, Register maskTemp,
- Register output, wasm::ZeroExtendIndex zeroExtend)
+ FaultingCodeRange wasmCompareExchange(const wasm::MemoryAccessDesc& access,
+ const BaseIndex& mem, Register expected,
+ Register replacement,
+ Register valueTemp, Register offsetTemp,
+ Register maskTemp, Register output,
+ wasm::ZeroExtendIndex zeroExtend)
DEFINED_ON(loong64, riscv64);
- void wasmAtomicExchange(const wasm::MemoryAccessDesc& access,
- const Address& mem, Register value, Register output)
+ FaultingCodeRange wasmAtomicExchange(const wasm::MemoryAccessDesc& access,
+ const Address& mem, Register value,
+ Register output)
DEFINED_ON(arm, arm64, x86_shared);
- void wasmAtomicExchange(const wasm::MemoryAccessDesc& access,
- const BaseIndex& mem, Register value, Register output)
+ FaultingCodeRange wasmAtomicExchange(const wasm::MemoryAccessDesc& access,
+ const BaseIndex& mem, Register value,
+ Register output)
DEFINED_ON(arm, arm64, x86_shared);
- void wasmAtomicExchange(const wasm::MemoryAccessDesc& access,
- const Address& mem, Register value,
- Register valueTemp, Register offsetTemp,
- Register maskTemp, Register output)
+ FaultingCodeRange wasmAtomicExchange(const wasm::MemoryAccessDesc& access,
+ const Address& mem, Register value,
+ Register valueTemp, Register offsetTemp,
+ Register maskTemp, Register output)
DEFINED_ON(mips64, loong64, riscv64);
- void wasmAtomicExchange(const wasm::MemoryAccessDesc& access,
- const BaseIndex& mem, Register value,
- Register valueTemp, Register offsetTemp,
- Register maskTemp, Register output)
+ FaultingCodeRange wasmAtomicExchange(const wasm::MemoryAccessDesc& access,
+ const BaseIndex& mem, Register value,
+ Register valueTemp, Register offsetTemp,
+ Register maskTemp, Register output)
DEFINED_ON(mips64, loong64, riscv64);
- void wasmAtomicExchange(const wasm::MemoryAccessDesc& access,
- const BaseIndex& mem, Register value,
- Register valueTemp, Register offsetTemp,
- Register maskTemp, Register output,
- wasm::ZeroExtendIndex zeroExtend)
+ FaultingCodeRange wasmAtomicExchange(const wasm::MemoryAccessDesc& access,
+ const BaseIndex& mem, Register value,
+ Register valueTemp, Register offsetTemp,
+ Register maskTemp, Register output,
+ wasm::ZeroExtendIndex zeroExtend)
DEFINED_ON(loong64, riscv64);
- void wasmAtomicFetchOp(const wasm::MemoryAccessDesc& access, AtomicOp op,
- Register value, const Address& mem, Register temp,
- Register output) DEFINED_ON(arm, arm64, x86_shared);
+ FaultingCodeRange wasmAtomicFetchOp(const wasm::MemoryAccessDesc& access,
+ AtomicOp op, Register value,
+ const Address& mem, Register temp,
+ Register output)
+ DEFINED_ON(arm, arm64, x86_shared);
- void wasmAtomicFetchOp(const wasm::MemoryAccessDesc& access, AtomicOp op,
- Imm32 value, const Address& mem, Register temp,
- Register output) DEFINED_ON(x86_shared);
+ FaultingCodeRange wasmAtomicFetchOp(const wasm::MemoryAccessDesc& access,
+ AtomicOp op, Imm32 value,
+ const Address& mem, Register temp,
+ Register output) DEFINED_ON(x86_shared);
- void wasmAtomicFetchOp(const wasm::MemoryAccessDesc& access, AtomicOp op,
- Register value, const BaseIndex& mem, Register temp,
- Register output) DEFINED_ON(arm, arm64, x86_shared);
+ FaultingCodeRange wasmAtomicFetchOp(const wasm::MemoryAccessDesc& access,
+ AtomicOp op, Register value,
+ const BaseIndex& mem, Register temp,
+ Register output)
+ DEFINED_ON(arm, arm64, x86_shared);
- void wasmAtomicFetchOp(const wasm::MemoryAccessDesc& access, AtomicOp op,
- Imm32 value, const BaseIndex& mem, Register temp,
- Register output) DEFINED_ON(x86_shared);
+ FaultingCodeRange wasmAtomicFetchOp(const wasm::MemoryAccessDesc& access,
+ AtomicOp op, Imm32 value,
+ const BaseIndex& mem, Register temp,
+ Register output) DEFINED_ON(x86_shared);
- void wasmAtomicFetchOp(const wasm::MemoryAccessDesc& access, AtomicOp op,
- Register value, const Address& mem, Register valueTemp,
- Register offsetTemp, Register maskTemp,
- Register output) DEFINED_ON(mips64, loong64, riscv64);
+ FaultingCodeRange wasmAtomicFetchOp(const wasm::MemoryAccessDesc& access,
+ AtomicOp op, Register value,
+ const Address& mem, Register valueTemp,
+ Register offsetTemp, Register maskTemp,
+ Register output)
+ DEFINED_ON(mips64, loong64, riscv64);
void wasmAtomicFetchOp(const wasm::MemoryAccessDesc& access, AtomicOp op,
Register value, const BaseIndex& mem,
@@ -4713,13 +4759,15 @@ class MacroAssembler : public MacroAssemblerSpecific {
// x86: `temp` must be ecx:ebx; `output` must be edx:eax.
// ARM: `temp` should be invalid; `output` must be (even,odd) pair.
- void wasmAtomicLoad64(const wasm::MemoryAccessDesc& access,
- const Address& mem, Register64 temp, Register64 output)
+ FaultingCodeRange wasmAtomicLoad64(const wasm::MemoryAccessDesc& access,
+ const Address& mem, Register64 temp,
+ Register64 output)
DEFINED_ON(arm, x86, wasm32);
- void wasmAtomicLoad64(const wasm::MemoryAccessDesc& access,
- const BaseIndex& mem, Register64 temp,
- Register64 output) DEFINED_ON(arm, x86, wasm32);
+ FaultingCodeRange wasmAtomicLoad64(const wasm::MemoryAccessDesc& access,
+ const BaseIndex& mem, Register64 temp,
+ Register64 output)
+ DEFINED_ON(arm, x86, wasm32);
// x86: `expected` must be the same as `output`, and must be edx:eax.
// x86: `replacement` must be ecx:ebx.
@@ -4729,15 +4777,17 @@ class MacroAssembler : public MacroAssemblerSpecific {
// ARM64: The base register in `mem` must not overlap `output`.
// MIPS: Registers must be distinct.
- void wasmCompareExchange64(const wasm::MemoryAccessDesc& access,
- const Address& mem, Register64 expected,
- Register64 replacement,
- Register64 output) PER_ARCH;
+ FaultingCodeRange wasmCompareExchange64(const wasm::MemoryAccessDesc& access,
+ const Address& mem,
+ Register64 expected,
+ Register64 replacement,
+ Register64 output) PER_ARCH;
- void wasmCompareExchange64(const wasm::MemoryAccessDesc& access,
- const BaseIndex& mem, Register64 expected,
- Register64 replacement,
- Register64 output) PER_ARCH;
+ FaultingCodeRange wasmCompareExchange64(const wasm::MemoryAccessDesc& access,
+ const BaseIndex& mem,
+ Register64 expected,
+ Register64 replacement,
+ Register64 output) PER_ARCH;
void wasmCompareExchange64(const wasm::MemoryAccessDesc& access,
const BaseIndex& mem, Register64 expected,
@@ -4750,13 +4800,13 @@ class MacroAssembler : public MacroAssemblerSpecific {
// pairs.
// MIPS: Registers must be distinct.
- void wasmAtomicExchange64(const wasm::MemoryAccessDesc& access,
- const Address& mem, Register64 value,
- Register64 output) PER_ARCH;
+ FaultingCodeRange wasmAtomicExchange64(const wasm::MemoryAccessDesc& access,
+ const Address& mem, Register64 value,
+ Register64 output) PER_ARCH;
- void wasmAtomicExchange64(const wasm::MemoryAccessDesc& access,
- const BaseIndex& mem, Register64 value,
- Register64 output) PER_ARCH;
+ FaultingCodeRange wasmAtomicExchange64(const wasm::MemoryAccessDesc& access,
+ const BaseIndex& mem, Register64 value,
+ Register64 output) PER_ARCH;
void wasmAtomicExchange64(const wasm::MemoryAccessDesc& access,
const BaseIndex& mem, Register64 value,
@@ -4769,14 +4819,16 @@ class MacroAssembler : public MacroAssemblerSpecific {
// pairs.
// MIPS: Registers must be distinct.
- void wasmAtomicFetchOp64(const wasm::MemoryAccessDesc& access, AtomicOp op,
... (file diff truncated)
Loading diff…
References
On This Page