High firefox Logic Error 🔧 Commit mapped

Overview

High
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Impacthigh
DescriptionUse-after-free in the DOM: HTML Parser component
ComponentDOM
Bug ClassLogic Error
Tracker2076271
Fix commitcc7a5b83a2d8 (firefox) +53/-3
CISA KEVNot listed
CreditedAmy Burnett of OpenAI
Disclosed2026-10-27

Changed Functions

FunctionChangeNotes
if
dom/xhr/XMLHttpRequestMainThread.cpp
modified

Files Changed

  • dom/xhr/XMLHttpRequestMainThread.cpp
  • parser/html/nsHtml5StreamParser.cpp
diff --git a/dom/xhr/XMLHttpRequestMainThread.cpp b/dom/xhr/XMLHttpRequestMainThread.cpp
index 71eee59ba93..0e1cd90df03 100644
--- a/dom/xhr/XMLHttpRequestMainThread.cpp
+++ b/dom/xhr/XMLHttpRequestMainThread.cpp
@@ -390,6 +390,16 @@ void XMLHttpRequestMainThread::SetAssociatedBrowsingContextID(uint64_t aId) {
 }
 
 void XMLHttpRequestMainThread::ResetResponse() {
+  if (RefPtr<nsXHRParseEndListener> listener = mParseEndListener.forget()) {
+    if (mResponseXML) {
+      if (EventListenerManager* manager =
+              mResponseXML->GetExistingListenerManager()) {
+        manager->RemoveEventListenerByType(listener,
+                                           kLiteralString_DOMContentLoaded,
+                                           TrustedEventsAtSystemGroupBubble());
+      }
+    }
+  }
   mResponseXML = nullptr;
   mResponseBody.Truncate();
   TruncateResponseText();
@@ -1051,6 +1061,9 @@ void XMLHttpRequestMainThread::CloseRequest(nsresult detail) {
                                "XMLHttpRequestMainThread::CloseRequest"_ns);
   }
   CancelTimeoutTimer();
+  if (mResponseXML) {
+    mResponseXML->StopDocumentLoad();
+  }
 }
 
 void XMLHttpRequestMainThread::CloseRequestWithError(
@@ -2009,6 +2022,30 @@ XMLHttpRequestMainThread::OnStartRequest(nsIRequest* request) {
     ChangeState(XMLHttpRequest_Binding::HEADERS_RECEIVED);
   }
 
+  // Re-run earlier check after scripts may have changed the state.
+
+  if (request != mChannel) {
+    // Can this still happen?
+    return NS_OK;
+  }
+
+  // Don't do anything if we have been aborted
+  if (mState == XMLHttpRequest_Binding::UNSENT) {
+    return NS_OK;
+  }
+
+  // Don't do anything if we're in mid-abort, but let the request
+  // know (this can happen due to race conditions in valid XHRs,
+  // see bz1070763 for info).
+  if (mFlagAborted) {
+    return NS_BINDING_ABORTED;
+  }
+
+  // Don't do anything if we have timed out.
+  if (mFlagTimedOut) {
+    return NS_OK;
+  }
+
   ResetResponse();
 
   if (!mOverrideMimeType.IsEmpty()) {
diff --git a/parser/html/nsHtml5StreamParser.cpp b/parser/html/nsHtml5StreamParser.cpp
index 16d212cf5f6..9191a8b1bf6 100644
--- a/parser/html/nsHtml5StreamParser.cpp
+++ b/parser/html/nsHtml5StreamParser.cpp
@@ -110,11 +110,24 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(nsHtml5StreamParser)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsHtml5StreamParser)
   tmp->DropTimer();
+  tmp->Terminate();
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mRequest)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner)
-  tmp->mExecutorFlusher = nullptr;
-  tmp->mLoadFlusher = nullptr;
-  tmp->mExecutor = nullptr;
+
+  // At this point, tasks on the parser thread can still
+  // execute. We have a mechanism for making sure that the
+  // stream parser stays alive for long enough. However, the
+  // way tree ops make their way into the executor happens
+  // through non-owning references, so we must not allow
+  // `mExecutor` to be deleted too early.
+  // `mExecutor` itself is a plain pointer, because
+  // `mLoadFlusher`, and `mExecutorFlusher` hold strong
+  // refs. Even though cycle collection traversal goes
+  // through them to discover a cycle, we deliberately
+  // don't set them to `nullptr` here to make sure that
+  // the executor stays around for as long as the stream
+  // parser stays around. We trust the cycle to be broken
+  // at some other edge of the cycle.
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsHtml5StreamParser)
Loading diff…