High firefox Memory Corruption 🔧 Commit mapped

Overview

High
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
Impacthigh
DescriptionMemory safety bugs present in Firefox 141 and Thunderbird 141. Some of these bugs showed evidence of memory corruption and we presume that with enough effort some of these could have been exploited to run arbitrary code.
ComponentSpiderMonkey
Bug ClassMemory Corruption
Tracker1825621
Fix commit42c192b6cba4 (firefox) +28/-0
CISA KEVNot listed
CreditedAndy Leiserson, Maurice Dauer, Sebastian Hengst and the Mozilla Fuzzing Team
Disclosed2025-08-19

Changed Functions

FunctionChangeNotes
JSONPrinter
js/src/vm/StringType.h
modified
PropertyName
js/src/vm/StringType.h
modified
StringBuilder
js/src/vm/StringType.h
modified
JSOffThreadAtom
js/src/vm/StringType.h
modified
ParserAtomsTable
js/src/vm/StringType.h
modified

Files Changed

  • js/src/gc/Cell.h
  • js/src/vm/StringType.h
diff --git a/js/src/gc/Cell.h b/js/src/gc/Cell.h
index 7a7d455ae37..b4ed6086f5d 100644
--- a/js/src/gc/Cell.h
+++ b/js/src/gc/Cell.h
@@ -627,8 +627,18 @@ class alignas(gc::CellAlignBytes) CellWithLengthAndFlags : public Cell {
     return uint32_t(header_.get() >> 32);
 #endif
   }
+  uint32_t headerLengthFieldAtomic() const {
+#if JS_BITS_PER_WORD == 32
+    return length_;
+#else
+    return uint32_t(header_.getAtomic() >> 32);
+#endif
+  }
 
   uint32_t headerFlagsField() const { return uint32_t(header_.get()); }
+  uint32_t headerFlagsFieldAtomic() const {
+    return uint32_t(header_.getAtomic());
+  }
 
   void setHeaderFlagBit(uint32_t flag) {
     header_.set(header_.get() | uintptr_t(flag));
diff --git a/js/src/vm/StringType.h b/js/src/vm/StringType.h
index ed4142a10ef..9eee35a4474 100644
--- a/js/src/vm/StringType.h
+++ b/js/src/vm/StringType.h
@@ -48,6 +48,7 @@ class JS_PUBLIC_API GenericPrinter;
 class JSONPrinter;
 class PropertyName;
 class StringBuilder;
+class JSOffThreadAtom;
 
 namespace frontend {
 class ParserAtomsTable;
@@ -736,6 +737,12 @@ class JSString : public js::gc::CellWithLengthAndFlags {
     return *(JSAtom*)this;
   }
 
+  MOZ_ALWAYS_INLINE
+  js::JSOffThreadAtom& asOffThreadAtom() const {
+    MOZ_ASSERT(headerFlagsFieldAtomic() & ATOM_BIT);
+    return *(js::JSOffThreadAtom*)this;
+  }
+
   MOZ_ALWAYS_INLINE
   void setNonDeduplicatable() {
     MOZ_ASSERT(isLinear());
@@ -1799,6 +1806,17 @@ class StringSegmentRange {
   }
 };
 
+// This class should be used in code that manipulates strings off-thread (for
+// example, Ion compilation). The key difference is that flags are loaded
+// atomically, preventing data races if flags (especially the pinned atom bit)
+// are mutated on the main thread. We use private inheritance to avoid
+// accidentally exposing anything non-thread-safe.
+class JSOffThreadAtom : private JSAtom {
+ public:
+  size_t length() const { return headerLengthFieldAtomic(); }
+  size_t flags() const { return headerFlagsFieldAtomic(); }
+};
+
 }  // namespace js
 
 inline js::HashNumber JSAtom::hash() const {
Loading diff…