Low firefox Memory Corruption 🔧 Commit mapped

Overview

Low
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
Impactlow
DescriptionA potential memory corruption vulnerability could be triggered if an attacker had the ability to trigger an OOM at a specific moment during JIT compilation.
ComponentSpiderMonkey
Bug ClassMemory Corruption
Tracker1915249
Fix commitbbc38e6bfd7c (firefox) +32/-23
CISA KEVNot listed
CreditedGary Kwong
Disclosed2024-10-01

Changed Functions

FunctionChangeNotes
while
js/src/jit/IonAnalysis.cpp
modified

Files Changed

  • js/src/jit/IonAnalysis.cpp
diff --git a/js/src/jit/IonAnalysis.cpp b/js/src/jit/IonAnalysis.cpp
index 8c37105b238..affbdafd7fc 100644
--- a/js/src/jit/IonAnalysis.cpp
+++ b/js/src/jit/IonAnalysis.cpp
@@ -29,8 +29,9 @@ using MPhiUseIteratorStack =
 
 // Look for Phi uses with a depth-first search. If any uses are found the stack
 // of MPhi instructions is returned in the |worklist| argument.
-static bool DepthFirstSearchUse(MIRGenerator* mir,
-                                MPhiUseIteratorStack& worklist, MPhi* phi) {
+[[nodiscard]] static bool DepthFirstSearchUse(MIRGenerator* mir,
+                                              MPhiUseIteratorStack& worklist,
+                                              MPhi* phi) {
   // Push a Phi and the next use to iterate over in the worklist.
   auto push = [&worklist](MPhi* phi, MUseIterator use) -> bool {
     phi->setInWorklist();
@@ -131,9 +132,9 @@ static bool DepthFirstSearchUse(MIRGenerator* mir,
   return true;
 }
 
-static bool FlagPhiInputsAsImplicitlyUsed(MIRGenerator* mir, MBasicBlock* block,
-                                          MBasicBlock* succ,
-                                          MPhiUseIteratorStack& worklist) {
+[[nodiscard]] static bool FlagPhiInputsAsImplicitlyUsed(
+    MIRGenerator* mir, MBasicBlock* block, MBasicBlock* succ,
+    MPhiUseIteratorStack& worklist) {
   // When removing an edge between 2 blocks, we might remove the ability of
   // later phases to figure out that the uses of a Phi should be considered as
   // a use of all its inputs. Thus we need to mark the Phi inputs as being
@@ -265,7 +266,7 @@ static MInstructionIterator FindFirstInstructionAfterBail(MBasicBlock* block) {
 
 // Given an iterator pointing to the first removed instruction, mark
 // the operands of each removed instruction as having implicit uses.
-static bool FlagOperandsAsImplicitlyUsedAfter(
+[[nodiscard]] static bool FlagOperandsAsImplicitlyUsedAfter(
     MIRGenerator* mir, MBasicBlock* block, MInstructionIterator firstRemoved) {
   MOZ_ASSERT(firstRemoved->block() == block);
 
@@ -312,8 +313,8 @@ static bool FlagOperandsAsImplicitlyUsedAfter(
   return true;
 }
 
-static bool FlagEntryResumePointOperands(MIRGenerator* mir,
-                                         MBasicBlock* block) {
+[[nodiscard]] static bool FlagEntryResumePointOperands(MIRGenerator* mir,
+                                                       MBasicBlock* block) {
   // Flag observable operands of the entry resume point as having implicit uses.
   MResumePoint* rp = block->entryResumePoint();
   while (rp) {
@@ -334,8 +335,8 @@ static bool FlagEntryResumePointOperands(MIRGenerator* mir,
   return true;
 }
 
-static bool FlagAllOperandsAsImplicitlyUsed(MIRGenerator* mir,
-                                            MBasicBlock* block) {
+[[nodiscard]] static bool FlagAllOperandsAsImplicitlyUsed(MIRGenerator* mir,
+                                                          MBasicBlock* block) {
   return FlagEntryResumePointOperands(mir, block) &&
          FlagOperandsAsImplicitlyUsedAfter(mir, block, block->begin());
 }
@@ -420,12 +421,16 @@ bool jit::PruneUnusedBranches(MIRGenerator* mir, MIRGraph& graph) {
     if (!block->isMarked()) {
       // If we are removing the block entirely, mark the operands of every
       // instruction as being implicitly used.
-      FlagAllOperandsAsImplicitlyUsed(mir, block);
+      if (!FlagAllOperandsAsImplicitlyUsed(mir, block)) {
+        return false;
+      }
     } else if (block->alwaysBails()) {
       // If we are only trimming instructions after a bail, only mark operands
       // of removed instructions.
       MInstructionIterator firstRemoved = FindFirstInstructionAfterBail(block);
-      FlagOperandsAsImplicitlyUsedAfter(mir, block, firstRemoved);
+      if (!FlagOperandsAsImplicitlyUsedAfter(mir, block, firstRemoved)) {
+        return false;
+      }
     }
   }
 
@@ -503,7 +508,8 @@ bool jit::PruneUnusedBranches(MIRGenerator* mir, MIRGraph& graph) {
   return true;
 }
 
-static bool SplitCriticalEdgesForBlock(MIRGraph& graph, MBasicBlock* block) {
+[[nodiscard]] static bool SplitCriticalEdgesForBlock(MIRGraph& graph,
+                                                     MBasicBlock* block) {
   if (block->numSuccessors() < 2) {
     return true;
   }
@@ -767,8 +773,8 @@ static bool IsDiamondPattern(MBasicBlock* initialBlock) {
   return true;
 }
 
-static bool MaybeFoldDiamondConditionBlock(MIRGraph& graph,
-                                           MBasicBlock* initialBlock) {
+[[nodiscard]] static bool MaybeFoldDiamondConditionBlock(
+    MIRGraph& graph, MBasicBlock* initialBlock) {
   MOZ_ASSERT(IsDiamondPattern(initialBlock));
 
   // Optimize the MIR graph to improve the code generated for conditional
@@ -936,8 +942,8 @@ static bool IsTrianglePattern(MBasicBlock* initialBlock) {
   return false;
 }
 
-static bool MaybeFoldTriangleConditionBlock(MIRGraph& graph,
-                                            MBasicBlock* initialBlock) {
+[[nodiscard]] static bool MaybeFoldTriangleConditionBlock(
+    MIRGraph& graph, MBasicBlock* initialBlock) {
   MOZ_ASSERT(IsTrianglePattern(initialBlock));
 
   // Optimize the MIR graph to improve the code generated for boolean
@@ -1089,8 +1095,8 @@ static bool MaybeFoldTriangleConditionBlock(MIRGraph& graph,
   return true;
 }
 
-static bool MaybeFoldConditionBlock(MIRGraph& graph,
-                                    MBasicBlock* initialBlock) {
+[[nodiscard]] static bool MaybeFoldConditionBlock(MIRGraph& graph,
+                                                  MBasicBlock* initialBlock) {
   if (IsDiamondPattern(initialBlock)) {
     return MaybeFoldDiamondConditionBlock(graph, initialBlock);
   }
@@ -1100,7 +1106,8 @@ static bool MaybeFoldConditionBlock(MIRGraph& graph,
   return true;
 }
 
-static bool MaybeFoldTestBlock(MIRGraph& graph, MBasicBlock* initialBlock) {
+[[nodiscard]] static bool MaybeFoldTestBlock(MIRGraph& graph,
+                                             MBasicBlock* initialBlock) {
   // Handle test expressions on more than two inputs. For example
   // |if ((x > 10) && (y > 20) && (z > 30)) { ... }|, which results in the below
   // pattern.
@@ -2984,7 +2991,9 @@ bool jit::RemoveUnmarkedBlocks(MIRGenerator* mir, MIRGraph& graph,
         continue;
       }
 
-      FlagAllOperandsAsImplicitlyUsed(mir, block);
+      if (!FlagAllOperandsAsImplicitlyUsed(mir, block)) {
+        return false;
+      }
     }
 
     // Find unmarked blocks and remove them.
@@ -4235,8 +4244,8 @@ bool jit::EliminateRedundantShapeGuards(MIRGraph& graph) {
   return true;
 }
 
-static bool TryEliminateGCBarriersForAllocation(TempAllocator& alloc,
-                                                MInstruction* allocation) {
+[[nodiscard]] static bool TryEliminateGCBarriersForAllocation(
+    TempAllocator& alloc, MInstruction* allocation) {
   MOZ_ASSERT(allocation->type() == MIRType::Object);
 
   JitSpew(JitSpew_RedundantGCBarriers, "Analyzing allocation %s",
Loading diff…