High firefox Logic Error 🔧 Commit mapped

Overview

High
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
Impacthigh
DescriptionIncorrect boundary conditions in the JavaScript Engine: JIT component
ComponentSpiderMonkey
Bug ClassLogic Error
Tracker2036978
Fix commiteaddf8af8ac0 (firefox) +15/-15
CISA KEVNot listed
Creditedggwhyp
Disclosed2026-05-12

Files Changed

  • js/src/jit/IonTypes.h
  • js/src/jit/Snapshots.cpp
  • js/src/jit/Snapshots.h
diff --git a/js/src/jit/IonTypes.h b/js/src/jit/IonTypes.h
index fcde4a6d591..8c42cb63263 100644
--- a/js/src/jit/IonTypes.h
+++ b/js/src/jit/IonTypes.h
@@ -41,7 +41,7 @@ class IonCompilationId {
 
 namespace jit {
 
-using RecoverOffset = uint32_t;
+using RecoverOffset = uint64_t;
 using SnapshotOffset = uint32_t;
 
 // The maximum size of any buffer associated with an assembler or code object.
@@ -52,8 +52,8 @@ static const uint32_t MAX_BUFFER_SIZE = (1 << 30) - 1;
 // Maximum number of scripted arg slots.
 static const uint32_t SNAPSHOT_MAX_NARGS = 127;
 
-static const SnapshotOffset INVALID_RECOVER_OFFSET = uint32_t(-1);
-static const SnapshotOffset INVALID_SNAPSHOT_OFFSET = uint32_t(-1);
+static const RecoverOffset INVALID_RECOVER_OFFSET = RecoverOffset(-1);
+static const SnapshotOffset INVALID_SNAPSHOT_OFFSET = SnapshotOffset(-1);
 
 /*
  * [SMDOC] Avoiding repeated bailouts / invalidations
diff --git a/js/src/jit/Snapshots.cpp b/js/src/jit/Snapshots.cpp
index 35a3507ce86..93d05a0bd14 100644
--- a/js/src/jit/Snapshots.cpp
+++ b/js/src/jit/Snapshots.cpp
@@ -49,7 +49,7 @@ using namespace js::jit;
 //
 // Snapshot header:
 //
-//   [vwu] bits ((n+1)-31]: recover instruction offset
+//   [vwu] bits ((n+1),63]: recover instruction offset
 //         bits [0,n): bailout kind (n = SNAPSHOT_BAILOUTKIND_BITS)
 //
 // Snapshot body, repeated "frame count" times, from oldest frame to newest
@@ -504,12 +504,12 @@ SnapshotReader::SnapshotReader(const uint8_t* snapshots, uint32_t offset,
 }
 
 #define COMPUTE_SHIFT_AFTER_(name) (name##_BITS + name##_SHIFT)
-#define COMPUTE_MASK_(name) ((uint32_t(1 << name##_BITS) - 1) << name##_SHIFT)
+#define COMPUTE_MASK_(name) (((uint64_t(1) << name##_BITS) - 1) << name##_SHIFT)
 
 // Details of snapshot header packing.
 static const uint32_t SNAPSHOT_BAILOUTKIND_SHIFT = 0;
 static const uint32_t SNAPSHOT_BAILOUTKIND_BITS = 6;
-static const uint32_t SNAPSHOT_BAILOUTKIND_MASK =
+static const uint64_t SNAPSHOT_BAILOUTKIND_MASK =
     COMPUTE_MASK_(SNAPSHOT_BAILOUTKIND);
 
 static_assert((1 << SNAPSHOT_BAILOUTKIND_BITS) - 1 >=
@@ -518,14 +518,14 @@ static_assert((1 << SNAPSHOT_BAILOUTKIND_BITS) - 1 >=
 
 static const uint32_t SNAPSHOT_ROFFSET_SHIFT =
     COMPUTE_SHIFT_AFTER_(SNAPSHOT_BAILOUTKIND);
-static const uint32_t SNAPSHOT_ROFFSET_BITS = 32 - SNAPSHOT_ROFFSET_SHIFT;
-static const uint32_t SNAPSHOT_ROFFSET_MASK = COMPUTE_MASK_(SNAPSHOT_ROFFSET);
+static const uint32_t SNAPSHOT_ROFFSET_BITS = 64 - SNAPSHOT_ROFFSET_SHIFT;
+static const uint64_t SNAPSHOT_ROFFSET_MASK = COMPUTE_MASK_(SNAPSHOT_ROFFSET);
 
 #undef COMPUTE_MASK_
 #undef COMPUTE_SHIFT_AFTER_
 
 void SnapshotReader::readSnapshotHeader() {
-  uint32_t bits = reader_.readUnsigned();
+  uint64_t bits = reader_.readUnsigned64();
 
   bailoutKind_ = BailoutKind((bits & SNAPSHOT_BAILOUTKIND_MASK) >>
                              SNAPSHOT_BAILOUTKIND_SHIFT);
@@ -633,15 +633,15 @@ SnapshotOffset SnapshotWriter::startSnapshot(RecoverOffset recoverOffset,
   allocWritten_ = 0;
 
   JitSpew(JitSpew_IonSnapshots,
-          "starting snapshot with recover offset %u, bailout kind %u",
+          "starting snapshot with recover offset %" PRIu64 ", bailout kind %u",
           recoverOffset, uint32_t(kind));
 
-  MOZ_ASSERT(uint32_t(kind) < (1 << SNAPSHOT_BAILOUTKIND_BITS));
-  MOZ_ASSERT(recoverOffset < (1 << SNAPSHOT_ROFFSET_BITS));
-  uint32_t bits = (uint32_t(kind) << SNAPSHOT_BAILOUTKIND_SHIFT) |
+  MOZ_ASSERT(uint64_t(kind) < (uint64_t(1) << SNAPSHOT_BAILOUTKIND_BITS));
+  MOZ_ASSERT(recoverOffset < (RecoverOffset(1) << SNAPSHOT_ROFFSET_BITS));
+  uint64_t bits = (uint64_t(kind) << SNAPSHOT_BAILOUTKIND_SHIFT) |
                   (recoverOffset << SNAPSHOT_ROFFSET_SHIFT);
 
-  writer_.writeUnsigned(bits);
+  writer_.writeUnsigned64(bits);
   return lastStart_;
 }
 
diff --git a/js/src/jit/Snapshots.h b/js/src/jit/Snapshots.h
index e4bf0268b7b..5fbd5039cf5 100644
--- a/js/src/jit/Snapshots.h
+++ b/js/src/jit/Snapshots.h
@@ -485,7 +485,7 @@ class RecoverWriter {
   uint32_t instructionsWritten_ = 0;
 
  public:
-  SnapshotOffset startRecover(uint32_t instructionCount);
+  RecoverOffset startRecover(uint32_t instructionCount);
 
   void writeInstruction(const MNode* rp);
 
Loading diff…