High firefox Logic Error 🔧 Commit mapped

Overview

High
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Impacthigh
DescriptionUse-after-free in the JavaScript: GC component
ComponentSpiderMonkey
Bug ClassLogic Error
Tracker2075296
Fix commit5faf0b483e46 (firefox) +57/-53
CISA KEVNot listed
CreditedMozilla
Disclosed2026-10-27

Changed Functions

FunctionChangeNotes
if
js/src/vm/JSContext.cpp
modified

Files Changed

  • js/src/gc/AtomMarking-inl.h
  • js/src/gc/AtomMarking.cpp
  • js/src/gc/AtomMarking.h
  • js/src/vm/JSContext.cpp
  • js/src/vm/JSContext.h
diff --git a/js/src/gc/AtomMarking-inl.h b/js/src/gc/AtomMarking-inl.h
index 2eeb4871811..9584c0a4d9f 100644
--- a/js/src/gc/AtomMarking-inl.h
+++ b/js/src/gc/AtomMarking-inl.h
@@ -216,6 +216,17 @@ MOZ_ALWAYS_INLINE bool AtomRefRuntime::inlinedRecordRefFallible(Zone* zone,
   return inlinedRecordRefInternal(zone, thing, lock);
 }
 
+template <typename T>
+void AtomRefRuntime::recordRef(JSContext* cx, T* thing) {
+  // Trigger a read barrier on the atom, in case there is an incremental
+  // GC in progress. This is necessary if the atom is being marked
+  // because a reference to it was obtained from another zone which is
+  // not being collected by the incremental GC.
+  ReadBarrier(thing);
+
+  inlinedRecordRefInfallible(cx->zone(), thing);
+}
+
 }  // namespace gc
 }  // namespace js
 
diff --git a/js/src/gc/AtomMarking.cpp b/js/src/gc/AtomMarking.cpp
index 960a77b763a..8cfad994783 100644
--- a/js/src/gc/AtomMarking.cpp
+++ b/js/src/gc/AtomMarking.cpp
@@ -360,46 +360,9 @@ void AtomRefRuntime::unmarkAllGrayReferences(GCRuntime* gc) {
   }
 }
 
-template <typename T>
-void AtomRefRuntime::recordRef(JSContext* cx, T* thing) {
-  // Trigger a read barrier on the atom, in case there is an incremental
-  // GC in progress. This is necessary if the atom is being marked
-  // because a reference to it was obtained from another zone which is
-  // not being collected by the incremental GC.
-  ReadBarrier(thing);
-
-  inlinedRecordRefInfallible(cx->zone(), thing);
-}
-
 template void AtomRefRuntime::recordRef(JSContext* cx, JSAtom* thing);
 template void AtomRefRuntime::recordRef(JSContext* cx, JS::Symbol* thing);
 
-void AtomRefRuntime::recordRefToId(JSContext* cx, jsid id) {
-  if (id.isAtom()) {
-    recordRef(cx, id.toAtom());
-    return;
-  }
-  if (id.isSymbol()) {
-    recordRef(cx, id.toSymbol());
-    return;
-  }
-  MOZ_ASSERT(!id.isGCThing());
-}
-
-void AtomRefRuntime::recordRefToValue(JSContext* cx, const Value& value) {
-  if (value.isString()) {
-    if (value.toString()->isAtom()) {
-      recordRef(cx, &value.toString()->asAtom());
-    }
-    return;
-  }
-  if (value.isSymbol()) {
-    recordRef(cx, value.toSymbol());
-    return;
-  }
-  MOZ_ASSERT(!value.isGCThing());
-}
-
 template <typename T>
 CellColor AtomRefRuntime::getRefColor(Zone* zone, T* thing) {
   static_assert(std::is_same_v<T, JSAtom> || std::is_same_v<T, JS::Symbol>,
diff --git a/js/src/gc/AtomMarking.h b/js/src/gc/AtomMarking.h
index 2db6b53e6a4..b258a8f92af 100644
--- a/js/src/gc/AtomMarking.h
+++ b/js/src/gc/AtomMarking.h
@@ -105,9 +105,6 @@ class AtomRefRuntime {
   [[nodiscard]] MOZ_ALWAYS_INLINE bool inlinedRecordRefFallible(Zone* zone,
                                                                 T* thing);
 
-  void recordRefToId(JSContext* cx, jsid id);
-  void recordRefToValue(JSContext* cx, const Value& value);
-
   // Get the reference color of |thing| in the atom reference bitmap for |zone|.
   template <typename T>
   CellColor getRefColor(Zone* zone, T* thing);
diff --git a/js/src/vm/JSContext.cpp b/js/src/vm/JSContext.cpp
index 7e6ccf7e955..87e676bd501 100644
--- a/js/src/vm/JSContext.cpp
+++ b/js/src/vm/JSContext.cpp
@@ -30,6 +30,7 @@
 #  include "debugger/ExecutionTracer.h"
 #endif
 #include "frontend/FrontendContext.h"
+#include "gc/AtomMarking.h"
 #include "gc/GC.h"
 #include "gc/PublicIterators.h"  // js::RealmsIter
 #include "irregexp/RegExpAPI.h"
@@ -1562,6 +1563,47 @@ JSScript* JSContext::currentScript(jsbytecode** ppc,
   return script;
 }
 
+void JSContext::recordRef(JSAtom* atom) {
+  atomReferences().recordRef(this, atom);
+}
+
+bool JSContext::wrapOrRecordRef(JS::MutableHandle<JS::Symbol*> symbol) {
+  atomReferences().recordRef(this, symbol.get());
+  return true;
+}
+
+bool JSContext::wrapOrRecordRefToId(JS::MutableHandle<jsid> id) {
+  if (id.isAtom()) {
+    atomReferences().recordRef(this, id.toAtom());
+    return true;
+  }
+
+  if (id.isSymbol()) {
+    atomReferences().recordRef(this, id.toSymbol());
+    return true;
+  }
+
+  MOZ_ASSERT(!id.isGCThing());
+  return true;
+}
+
+bool JSContext::wrapOrRecordRefToValue(JS::MutableHandle<JS::Value> value) {
+  if (value.isString()) {
+    if (value.toString()->isAtom()) {
+      atomReferences().recordRef(this, &value.toString()->asAtom());
+    }
+    return true;
+  }
+
+  if (value.isSymbol()) {
+    atomReferences().recordRef(this, value.toSymbol());
+    return true;
+  }
+
+  MOZ_ASSERT(!value.isGCThing());
+  return true;
+}
+
 #ifdef JS_CRASH_DIAGNOSTICS
 void ContextChecks::check(AbstractFramePtr frame, int argIndex) {
   if (frame) {
diff --git a/js/src/vm/JSContext.h b/js/src/vm/JSContext.h
index 224b80db712..0ee80aa3d15 100644
--- a/js/src/vm/JSContext.h
+++ b/js/src/vm/JSContext.h
@@ -435,19 +435,10 @@ struct JS_PUBLIC_API JSContext : public JS::RootingContext,
     return runtime_->gc.atomReferences;
   }
 
-  void recordRef(JSAtom* atom) { atomReferences().recordRef(this, atom); }
-  bool wrapOrRecordRef(JS::MutableHandle<JS::Symbol*> symbol) {
-    atomReferences().recordRef(this, symbol.get());
-    return true;
-  }
-  bool wrapOrRecordRefToId(JS::MutableHandle<jsid> id) {
-    atomReferences().recordRefToId(this, id);
-    return true;
-  }
-  bool wrapOrRecordRefToValue(JS::MutableHandle<JS::Value> value) {
-    atomReferences().recordRefToValue(this, value);
-    return true;
-  }
+  void recordRef(JSAtom* atom);
+  bool wrapOrRecordRef(JS::MutableHandle<JS::Symbol*> symbol);
+  bool wrapOrRecordRefToId(JS::MutableHandle<jsid> id);
+  bool wrapOrRecordRefToValue(JS::MutableHandle<JS::Value> value);
 
   // Interface for recording telemetry metrics.
   js::Metrics metrics() { return js::Metrics(runtime_); }
Loading diff…