Medium firefox UAF 🔧 Commit mapped

Overview

Medium
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
Impactmoderate
DescriptionUse-after-free in the JavaScript: WebAssembly component
ComponentSpiderMonkey
Bug ClassUAF
Tracker2013619
Fix commit7da3f3eae982 (firefox) +76/-42
CISA KEVNot listed
CreditedEvyatar Ben Asher, Keane Lucas, Nicholas Carlini, Newton Cheng, Daniel Freeman, Alex Gaynor, and Joel Weinberger using Claude from Anthropic
Disclosed2026-04-21

Changed Functions

FunctionChangeNotes
OutOfLineCode
js/src/wasm/WasmBCClass.h
modified
OutOfLineAbortingTrap
js/src/wasm/WasmBaselineCompile.cpp
modified
OutOfLineResumableTrap
js/src/wasm/WasmBaselineCompile.cpp
modified
OutOfLineTrap
js/src/wasm/WasmBaselineCompile.cpp
modified
if
js/src/wasm/WasmBaselineCompile.cpp
modified
lastOpcodeOffset_
js/src/wasm/WasmBaselineCompile.cpp
modified

Files Changed

  • js/src/wasm/WasmBCClass.h
  • js/src/wasm/WasmBCCodegen-inl.h
  • js/src/wasm/WasmBCFrame.cpp
  • js/src/wasm/WasmBaselineCompile.cpp
diff --git a/js/src/wasm/WasmBCClass.h b/js/src/wasm/WasmBCClass.h
index 99bf2ba09a7..976e3c3ac9e 100644
--- a/js/src/wasm/WasmBCClass.h
+++ b/js/src/wasm/WasmBCClass.h
@@ -32,6 +32,8 @@
 namespace js {
 namespace wasm {
 
+struct StackMap;
+
 // Container for a piece of out-of-line code, the slow path that supports an
 // operation.
 class OutOfLineCode;
@@ -957,6 +959,10 @@ struct BaseCompiler final {
   [[nodiscard]] bool createStackMap(
       const char* who, HasDebugFrameWithLiveRefs debugFrameWithLiveRefs);
 
+  // Creates a stack map for an aborting trap instruction that will be emitted
+  // OOL.
+  [[nodiscard]] bool createAbortingOutOfLineTrapStackMap(StackMap** result);
+
   ////////////////////////////////////////////////////////////
   //
   // Control stack
@@ -1362,7 +1368,10 @@ struct BaseCompiler final {
   inline TrapSiteDesc trapSiteDesc() const;
 
   // Generate a trap instruction for the current bytecodeOffset.
-  inline void trap(Trap t) const;
+  inline void trap(Trap t);
+
+  // Generate a trap instruction for given location and stack map.
+  inline void trap(Trap t, const TrapSiteDesc& trapSite, StackMap* stackMap);
 
   // Abstracted helper for throwing, used for throw, rethrow, and rethrowing
   // at the end of a series of catch blocks (if none matched the exception).
diff --git a/js/src/wasm/WasmBCCodegen-inl.h b/js/src/wasm/WasmBCCodegen-inl.h
index ca5a29b9fd7..896bc5165ab 100644
--- a/js/src/wasm/WasmBCCodegen-inl.h
+++ b/js/src/wasm/WasmBCCodegen-inl.h
@@ -211,7 +211,25 @@ RegRef BaseCompiler::captureReturnedRef() {
 //
 // Miscellaneous.
 
-void BaseCompiler::trap(Trap t) const { masm.wasmTrap(t, trapSiteDesc()); }
+void BaseCompiler::trap(Trap t) {
+  masm.wasmTrap(t, trapSiteDesc());
+
+  if (MOZ_LIKELY(!compilerEnv_.debugEnabled())) {
+    return;
+  }
+
+  masm.propagateOOM(
+      createStackMap("BaseCompiler::trap", HasDebugFrameWithLiveRefs::Maybe));
+}
+
+void BaseCompiler::trap(Trap t, const TrapSiteDesc& trapSite,
+                        StackMap* stackMap) {
+  masm.wasmTrap(t, trapSite);
+
+  if (stackMap && !stackMaps_->add(masm.currentOffset(), stackMap)) {
+    masm.setOOM();
+  }
+}
 
 void BaseCompiler::cmp64Set(Assembler::Condition cond, RegI64 lhs, RegI64 rhs,
                             RegI32 dest) {
diff --git a/js/src/wasm/WasmBCFrame.cpp b/js/src/wasm/WasmBCFrame.cpp
index cc2b1793420..45f3eeeed85 100644
--- a/js/src/wasm/WasmBCFrame.cpp
+++ b/js/src/wasm/WasmBCFrame.cpp
@@ -18,6 +18,7 @@
 
 #include "wasm/WasmBCFrame.h"
 
+#include "mozilla/Likely.h"
 #include "wasm/WasmBaselineCompile.h"  // For BaseLocalIter
 #include "wasm/WasmBCClass.h"
 
@@ -164,6 +165,18 @@ bool BaseCompiler::createStackMap(
          (!stackMap || stackMaps_->add(masm.currentOffset(), stackMap));
 }
 
+[[nodiscard]] bool BaseCompiler::createAbortingOutOfLineTrapStackMap(
+    StackMap** result) {
+  if (MOZ_LIKELY(!compilerEnv_.debugEnabled())) {
+    *result = nullptr;
+    return true;
+  }
+
+  ExitStubMapVector extras;
+  return stackMapGenerator_.createStackMap(
+      "OutOfLineTrap", extras, HasDebugFrameWithLiveRefs::Maybe, stk_, result);
+}
+
 bool MachineStackTracker::cloneTo(MachineStackTracker* dst) {
   MOZ_ASSERT(dst->vec_.empty());
   if (!dst->vec_.appendAll(vec_)) {
diff --git a/js/src/wasm/WasmBaselineCompile.cpp b/js/src/wasm/WasmBaselineCompile.cpp
index a231fed675b..2659565ce13 100644
--- a/js/src/wasm/WasmBaselineCompile.cpp
+++ b/js/src/wasm/WasmBaselineCompile.cpp
@@ -213,40 +213,23 @@ class OutOfLineCode : public TempObject {
   // All other registers must be explicitly saved and restored by the OOL code
   // before being used.
 
-  virtual void generate(MacroAssembler* masm) = 0;
+  virtual void generate(MacroAssembler* masm, BaseCompiler* bc) = 0;
 };
 
-class OutOfLineAbortingTrap : public OutOfLineCode {
-  Trap trap_;
-  TrapSiteDesc desc_;
-
- public:
-  OutOfLineAbortingTrap(Trap trap, const TrapSiteDesc& desc)
-      : trap_(trap), desc_(desc) {}
-
-  virtual void generate(MacroAssembler* masm) override {
-    masm->wasmTrap(trap_, desc_);
-    MOZ_ASSERT(!rejoin()->bound());
-  }
-};
-
-class OutOfLineResumableTrap : public OutOfLineCode {
+class OutOfLineTrap : public OutOfLineCode {
   Trap trap_;
   TrapSiteDesc desc_;
   wasm::StackMap* stackMap_;
-  wasm::StackMaps* stackMaps_;
 
  public:
-  OutOfLineResumableTrap(Trap trap, const TrapSiteDesc& desc,
-                         wasm::StackMap* stackMap, wasm::StackMaps* stackMaps)
-      : trap_(trap), desc_(desc), stackMap_(stackMap), stackMaps_(stackMaps) {}
+  OutOfLineTrap(Trap trap, const TrapSiteDesc& desc, wasm::StackMap* stackMap)
+      : trap_(trap), desc_(desc), stackMap_(stackMap) {}
 
-  virtual void generate(MacroAssembler* masm) override {
-    masm->wasmTrap(trap_, desc_);
-    if (stackMap_ && !stackMaps_->add(masm->currentOffset(), stackMap_)) {
-      masm->setOOM();
+  virtual void generate(MacroAssembler* masm, BaseCompiler* bc) override {
+    bc->trap(trap_, desc_, stackMap_);
+    if (rejoin()) {
+      masm->jump(rejoin());
     }
-    masm->jump(rejoin());
   }
 };
 
@@ -264,7 +247,7 @@ bool BaseCompiler::generateOutOfLineCode() {
       continue;
     }
     ool->bind(&fr, &masm);
-    ool->generate(&masm);
+    ool->generate(&masm, this);
   }
 
   return !masm.oom();
@@ -583,17 +566,16 @@ bool BaseCompiler::beginFunction() {
   }
 
   OutOfLineCode* oolStackOverflowTrap =
-      addOutOfLineCode(new (alloc_) OutOfLineAbortingTrap(
+      addOutOfLineCode(new (alloc_) OutOfLineTrap(
           Trap::StackOverflow,
-          TrapSiteDesc(BytecodeOffset(func_.lineOrBytecode))));
+          TrapSiteDesc(BytecodeOffset(func_.lineOrBytecode)), nullptr));
   if (!oolStackOverflowTrap) {
     return false;
   }
   fr.checkStack(ABINonArgReg0, ABINonArgReg1, oolStackOverflowTrap->entry());
 
-  OutOfLineCode* oolInterruptTrap = addOutOfLineCode(
-      new (alloc_) OutOfLineResumableTrap(Trap::CheckInterrupt, trapSiteDesc(),
-                                          functionEntryStackMap, stackMaps_));
+  OutOfLineCode* oolInterruptTrap = addOutOfLineCode(new (alloc_) OutOfLineTrap(
+      Trap::CheckInterrupt, trapSiteDesc(), functionEntryStackMap));
   if (!oolInterruptTrap) {
     return false;
   }
@@ -1128,7 +1110,7 @@ class OutOfLineRequestTierUp : public OutOfLineCode {
       : instance_(instance),
         scratch_(scratch),
         lastOpcodeOffset_(lastOpcodeOffset) {}
-  virtual void generate(MacroAssembler* masm) override {
+  virtual void generate(MacroAssembler* masm, BaseCompiler* bc) override {
     // Generate:
     //
     // [optionally, if `instance_` != InstanceReg: swap(instance_, InstanceReg)]
@@ -2071,8 +2053,12 @@ bool BaseCompiler::callIndirect(uint32_t funcTypeIndex, uint32_t tableIndex,
   CallSiteDesc desc(bytecodeOffset(), CallSiteKind::Indirect);
   CalleeDesc callee =
       CalleeDesc::wasmTable(codeMeta_, table, tableIndex, callIndirectId);
-  OutOfLineCode* oob = addOutOfLineCode(
-      new (alloc_) OutOfLineAbortingTrap(Trap::OutOfBounds, trapSiteDesc()));
+  StackMap* oobTrapStackMap;
+  if (!createAbortingOutOfLineTrapStackMap(&oobTrapStackMap)) {
+    return false;
Loading diff…