Medium firefox UAF 🔧 Commit mapped

Overview

Medium
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
Impactmoderate
DescriptionUse-after-free in the DOM: Window and Location component
ComponentToolkit
Bug ClassUAF
Tracker2014560
Fix commit052b1231ea0a (firefox) +26/-33
CISA KEVNot listed
CreditedEvyatar Ben Asher, Keane Lucas, Nicholas Carlini, Newton Cheng, Daniel Freeman, Alex Gaynor, and Joel Weinberger using Claude from Anthropic
Disclosed2026-02-24

Changed Functions

FunctionChangeNotes
if
toolkit/components/windowwatcher/nsWindowWatcher.cpp
modified
while
toolkit/components/windowwatcher/nsWindowWatcher.cpp
modified
AppWindow
xpfe/appshell/nsContentTreeOwner.h
modified

Files Changed

  • toolkit/components/windowwatcher/nsWindowWatcher.cpp
  • xpfe/appshell/nsContentTreeOwner.cpp
  • xpfe/appshell/nsContentTreeOwner.h
diff --git a/toolkit/components/windowwatcher/nsWindowWatcher.cpp b/toolkit/components/windowwatcher/nsWindowWatcher.cpp
index b113e07c85d..edb87cc05f6 100644
--- a/toolkit/components/windowwatcher/nsWindowWatcher.cpp
+++ b/toolkit/components/windowwatcher/nsWindowWatcher.cpp
@@ -90,15 +90,8 @@ class nsWindowWatcher;
 struct nsWatcherWindowEntry {
   nsWatcherWindowEntry(mozIDOMWindowProxy* aWindow,
                        nsIWebBrowserChrome* aChrome)
-      : mChrome(nullptr) {
-    mWindow = aWindow;
-    nsCOMPtr<nsISupportsWeakReference> supportsweak(do_QueryInterface(aChrome));
-    if (supportsweak) {
-      supportsweak->GetWeakReference(getter_AddRefs(mChromeWeak));
-    } else {
-      mChrome = aChrome;
-      mChromeWeak = nullptr;
-    }
+      : mWindow(do_GetWeakReference(aWindow)),
+        mChrome(do_GetWeakReference(aChrome)) {
     ReferenceSelf();
   }
   ~nsWatcherWindowEntry() = default;
@@ -107,9 +100,8 @@ struct nsWatcherWindowEntry {
   void Unlink();
   void ReferenceSelf();
 
-  mozIDOMWindowProxy* mWindow;
-  nsIWebBrowserChrome* mChrome;
-  nsWeakPtr mChromeWeak;
+  nsWeakPtr mWindow;
+  nsWeakPtr mChrome;
   // each struct is in a circular, doubly-linked list
   nsWatcherWindowEntry* mYounger;  // next younger in sequence
   nsWatcherWindowEntry* mOlder;
@@ -193,10 +185,15 @@ nsWatcherWindowEnumerator::GetNext(nsISupports** aResult) {
 
   *aResult = nullptr;
 
-  if (mCurrentPosition) {
-    CallQueryInterface(mCurrentPosition->mWindow, aResult);
+  while (mCurrentPosition) {
+    nsCOMPtr<mozIDOMWindowProxy> window =
+        do_QueryReferent(mCurrentPosition->mWindow);
+    if (window) {
+      CallQueryInterface(window, aResult);
+      mCurrentPosition = FindNext();
+      return NS_OK;
+    }
     mCurrentPosition = FindNext();
-    return NS_OK;
   }
   return NS_ERROR_FAILURE;
 }
@@ -1652,14 +1649,7 @@ nsWindowWatcher::AddWindow(mozIDOMWindowProxy* aWindow,
     // its chrome mapping and return
     info = FindWindowEntry(aWindow);
     if (info) {
-      nsCOMPtr<nsISupportsWeakReference> supportsweak(
-          do_QueryInterface(aChrome));
-      if (supportsweak) {
-        supportsweak->GetWeakReference(getter_AddRefs(info->mChromeWeak));
-      } else {
-        info->mChrome = aChrome;
-        info->mChromeWeak = nullptr;
-      }
+      info->mChrome = do_GetWeakReference(aChrome);
       return NS_OK;
     }
 
@@ -1713,7 +1703,8 @@ nsWatcherWindowEntry* nsWindowWatcher::FindWindowEntry(
   info = mOldestWindow;
   listEnd = nullptr;
   while (info != listEnd) {
-    if (info->mWindow == aWindow) {
+    nsCOMPtr<mozIDOMWindowProxy> window = do_QueryReferent(info->mWindow);
+    if (window && window == aWindow) {
       return info;
     }
     info = info->mYounger;
@@ -1744,8 +1735,11 @@ nsresult nsWindowWatcher::RemoveWindow(nsWatcherWindowEntry* aInfo) {
   // send notifications.
   nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
   if (os) {
-    nsCOMPtr<nsISupports> domwin(do_QueryInterface(aInfo->mWindow));
-    os->NotifyObservers(domwin, "domwindowclosed", nullptr);
+    nsCOMPtr<mozIDOMWindowProxy> window = do_QueryReferent(aInfo->mWindow);
+    if (window) {
+      nsCOMPtr<nsISupports> domwin(do_QueryInterface(window));
+      os->NotifyObservers(domwin, "domwindowclosed", nullptr);
+    }
   }
 
   delete aInfo;
@@ -1763,12 +1757,8 @@ nsWindowWatcher::GetChromeForWindow(mozIDOMWindowProxy* aWindow,
   MutexAutoLock lock(mListLock);
   nsWatcherWindowEntry* info = FindWindowEntry(aWindow);
   if (info) {
-    if (info->mChromeWeak) {
-      return info->mChromeWeak->QueryReferent(
-          NS_GET_IID(nsIWebBrowserChrome), reinterpret_cast<void**>(aResult));
-    }
-    *aResult = info->mChrome;
-    NS_IF_ADDREF(*aResult);
+    nsCOMPtr<nsIWebBrowserChrome> chrome = do_QueryReferent(info->mChrome);
+    chrome.forget(aResult);
   }
   return NS_OK;
 }
diff --git a/xpfe/appshell/nsContentTreeOwner.cpp b/xpfe/appshell/nsContentTreeOwner.cpp
index a349980ea3a..57f00f8b9ef 100644
--- a/xpfe/appshell/nsContentTreeOwner.cpp
+++ b/xpfe/appshell/nsContentTreeOwner.cpp
@@ -67,6 +67,7 @@ NS_INTERFACE_MAP_BEGIN(nsContentTreeOwner)
   NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome)
   NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
   NS_INTERFACE_MAP_ENTRY(nsIWindowProvider)
+  NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
 NS_INTERFACE_MAP_END
 
 //*****************************************************************************
diff --git a/xpfe/appshell/nsContentTreeOwner.h b/xpfe/appshell/nsContentTreeOwner.h
index eeeb2f00b1d..40a5844103a 100644
--- a/xpfe/appshell/nsContentTreeOwner.h
+++ b/xpfe/appshell/nsContentTreeOwner.h
@@ -18,6 +18,7 @@
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIWebBrowserChrome.h"
 #include "nsIWindowProvider.h"
+#include "nsWeakReference.h"
 
 namespace mozilla {
 class AppWindow;
@@ -27,7 +28,8 @@ class nsContentTreeOwner final : public nsIDocShellTreeOwner,
                                  public nsIBaseWindow,
                                  public nsIInterfaceRequestor,
                                  public nsIWebBrowserChrome,
-                                 public nsIWindowProvider {
+                                 public nsIWindowProvider,
+                                 public nsSupportsWeakReference {
   friend class mozilla::AppWindow;
 
  public:
Loading diff…