High firefox Logic Error 🔧 Commit mapped

Overview

High
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
Impacthigh
DescriptionJIT miscompilation in the JavaScript Engine: JIT component
ComponentSpiderMonkey
Bug ClassLogic Error
Tracker1992902
Fix commitde49b52ff5f9 (firefox) +57/-14
CISA KEVNot listed
CreditedProject KillFuzz of Qrious Secure
Disclosed2025-11-11

Changed Functions

FunctionChangeNotes
MTypedArraySubarray
js/src/jit/MIR.h
modified
initialHeap_
js/src/jit/MIR.h
modified
if
js/src/jit/MIR.h
modified
MEffectiveAddress3
js/src/jit/MIR.h
modified

Files Changed

  • js/src/jit/LIROps.yaml
  • js/src/jit/MIR.h
  • js/src/jit/MIROps.yaml
  • js/src/jit/ScalarReplacement.cpp
  • js/src/jit/WarpCacheIRTranspiler.cpp
diff --git a/js/src/jit/LIROps.yaml b/js/src/jit/LIROps.yaml
index afee00be4b0..25dec23c5a1 100644
--- a/js/src/jit/LIROps.yaml
+++ b/js/src/jit/LIROps.yaml
@@ -2333,6 +2333,15 @@
   num_temps: 1
   mir_op: StoreTypedArrayElementHole
 
+- name: TypedArraySubarray
+  result_type: WordSized
+  operands:
+    object: WordSized
+    start: WordSized
+    length: WordSized
+  call_instruction: true
+  mir_op: true
+
 - name: TypedArrayFill
   operands:
     object: WordSized
diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h
index 9acb4c2f79d..293c7ba0185 100644
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -7624,6 +7624,48 @@ class MTypedArrayFill : public MQuaternaryInstruction,
   ALLOW_CLONE(MTypedArrayFill)
 };
 
+// Inlined TypedArray.prototype.subarray
+class MTypedArraySubarray : public MTernaryInstruction,
+                            public MixPolicy<ObjectPolicy<0>, IntPtrPolicy<1>,
+                                             IntPtrPolicy<2>>::Data {
+  CompilerGCPointer<JSObject*> templateObject_;
+  gc::Heap initialHeap_;
+  bool scalarReplaced_ = false;
+
+  MTypedArraySubarray(MDefinition* object, MDefinition* start,
+                      MDefinition* length, JSObject* templateObject,
+                      gc::Heap initialHeap)
+      : MTernaryInstruction(classOpcode, object, start, length),
+        templateObject_(templateObject),
+        initialHeap_(initialHeap) {
+    setResultType(MIRType::Object);
+  }
+
+ public:
+  INSTRUCTION_HEADER(TypedArraySubarray)
+  TRIVIAL_NEW_WRAPPERS
+  NAMED_OPERANDS((0, object), (1, start), (2, length))
+
+  JSObject* templateObject() const { return templateObject_; }
+  gc::Heap initialHeap() const { return initialHeap_; }
+
+  bool isScalarReplaced() const { return scalarReplaced_; }
+  void setScalarReplaced() { scalarReplaced_ = true; }
+
+  AliasSet getAliasSet() const override {
+    if (scalarReplaced_) {
+      return AliasSet::None();
+    }
+    return AliasSet::Store(AliasSet::ObjectFields);
+  }
+
+  bool possiblyCalls() const override { return true; }
+
+  [[nodiscard]] bool writeRecoverData(
+      CompactBufferWriter& writer) const override;
+  bool canRecoverOnBailout() const override { return scalarReplaced_; }
+};
+
 // Compute a 3-component "effective address":
 //   base + index * scale + displacement
 class MEffectiveAddress3 : public MBinaryInstruction,
diff --git a/js/src/jit/MIROps.yaml b/js/src/jit/MIROps.yaml
index 134183f973f..6f70bdbca11 100644
--- a/js/src/jit/MIROps.yaml
+++ b/js/src/jit/MIROps.yaml
@@ -1923,18 +1923,7 @@
 
 # Inlined TypedArray.prototype.subarray
 - name: TypedArraySubarray
-  operands:
-    object: Object
-    start: IntPtr
-    length: IntPtr
-  arguments:
-    templateObject: JSObject*
-    initialHeap: gc::Heap
-  result_type: Object
-  alias_set: none
-  can_recover: true
-  possibly_calls: true
-  generate_lir: true
+  gen_boilerplate: false
 
 - name: ToIntegerIndex
   operands:
diff --git a/js/src/jit/ScalarReplacement.cpp b/js/src/jit/ScalarReplacement.cpp
index ac5f346874e..d1489d354af 100644
--- a/js/src/jit/ScalarReplacement.cpp
+++ b/js/src/jit/ScalarReplacement.cpp
@@ -3393,6 +3393,7 @@ void SubarrayReplacer::visitTypedArraySubarray(MTypedArraySubarray* ins) {
   if (!isSubarrayOrGuard(ins->object())) {
     return;
   }
+  MOZ_ASSERT(!ins->isScalarReplaced());
 
   // Add both |start| operands to get the adjusted start index.
   auto* newStart =
@@ -3402,6 +3403,7 @@ void SubarrayReplacer::visitTypedArraySubarray(MTypedArraySubarray* ins) {
   auto* replacement = MTypedArraySubarray::New(
       alloc(), subarray()->object(), newStart, ins->length(),
       ins->templateObject(), ins->initialHeap());
+  replacement->stealResumePoint(ins);
   ins->block()->insertBefore(ins, replacement);
 
   // Replace the subarray.
@@ -3530,6 +3532,7 @@ bool SubarrayReplacer::run() {
 }
 
 void SubarrayReplacer::assertSuccess() const {
+  subarray()->setScalarReplaced();
   MOZ_ASSERT(subarray_->canRecoverOnBailout());
   MOZ_ASSERT(!subarray_->hasLiveDefUses());
 }
diff --git a/js/src/jit/WarpCacheIRTranspiler.cpp b/js/src/jit/WarpCacheIRTranspiler.cpp
index 9a792de9553..db00525ff37 100644
--- a/js/src/jit/WarpCacheIRTranspiler.cpp
+++ b/js/src/jit/WarpCacheIRTranspiler.cpp
@@ -2555,10 +2555,10 @@ bool WarpCacheIRTranspiler::emitTypedArraySubarrayResult(
 
   auto* ins = MTypedArraySubarray::New(alloc(), obj, actualStart, length,
                                        templateObj, heap);
-  add(ins);
+  addEffectful(ins);
 
   pushResult(ins);
-  return true;
+  return resumeAfter(ins);
 }
 
 bool WarpCacheIRTranspiler::emitLinearizeForCharAccess(
Loading diff…