High firefox Logic Error 🔧 Commit mapped

Overview

High
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Impacthigh
DescriptionUse-after-free in the XML component
ComponentDOM
Bug ClassLogic Error
Tracker2073692
Fix commit133a822f130a (firefox) +23/-2
CISA KEVNot listed
CreditedMozilla
Disclosed2026-10-13

Changed Functions

FunctionChangeNotes
if
dom/xml/nsXMLPrettyPrinter.cpp
modified
nsXMLPrettyPrinter
dom/xml/nsXMLPrettyPrinter.h
modified

Files Changed

  • dom/xml/crashtests/2073692-frame.xml
  • dom/xml/crashtests/2073692.html
  • dom/xml/crashtests/crashtests.list
  • dom/xml/nsXMLPrettyPrinter.cpp
  • dom/xml/nsXMLPrettyPrinter.h
diff --git a/dom/xml/nsXMLPrettyPrinter.cpp b/dom/xml/nsXMLPrettyPrinter.cpp
index cdc23908680..fa4dfc5fab2 100644
--- a/dom/xml/nsXMLPrettyPrinter.cpp
+++ b/dom/xml/nsXMLPrettyPrinter.cpp
@@ -135,6 +135,7 @@ nsresult nsXMLPrettyPrinter::PrettyPrint(Document* aDocument,
   // Observe the document so we know when to switch to "normal" view
   aDocument->AddObserver(this);
   mDocument = aDocument;
+  mElement = do_GetWeakReference(rootElement);
 
   NS_ADDREF_THIS();
 
@@ -161,14 +162,14 @@ void nsXMLPrettyPrinter::MaybeUnhook(nsIContent* aContent) {
 
 void nsXMLPrettyPrinter::Unhook() {
   mDocument->RemoveObserver(this);
-  nsCOMPtr<Element> element = mDocument->GetDocumentElement();
+  nsCOMPtr<Element> element = do_QueryReferent(mElement);
 
   if (element) {
-    // Remove the shadow root
     element->UnattachShadow();
   }
 
   mDocument = nullptr;
+  mElement = nullptr;
 
   NS_RELEASE_THIS();
 }
@@ -199,6 +200,7 @@ void nsXMLPrettyPrinter::NodeWillBeDestroyed(nsINode* aNode) {
   MOZ_DIAGNOSTIC_ASSERT(mDocument == aNode);
   mDocument->RemoveMutationObserver(this);
   mDocument = nullptr;
+  mElement = nullptr;
   NS_RELEASE_THIS();
 }
 
diff --git a/dom/xml/nsXMLPrettyPrinter.h b/dom/xml/nsXMLPrettyPrinter.h
index b6a1b592513..8beca1084f1 100644
--- a/dom/xml/nsXMLPrettyPrinter.h
+++ b/dom/xml/nsXMLPrettyPrinter.h
@@ -6,6 +6,7 @@
 #define nsXMLPrettyPrinter_h_
 
 #include "nsCOMPtr.h"
+#include "nsIWeakReferenceUtils.h"
 #include "nsStubDocumentObserver.h"
 
 class nsXMLPrettyPrinter : public nsStubDocumentObserver {
@@ -51,6 +52,7 @@ class nsXMLPrettyPrinter : public nsStubDocumentObserver {
 
   mozilla::dom::Document*
       mDocument;  // weak. Set as long as we're observing the document
+  nsWeakPtr mElement;
   bool mUnhookPending;
 };
 
diff --git a/dom/xml/crashtests/2073692-frame.xml b/dom/xml/crashtests/2073692-frame.xml
new file mode 100644
index 00000000000..d56986231a9
--- /dev/null
+++ b/dom/xml/crashtests/2073692-frame.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0"?>
+<root>Pretty printed XML</root>
diff --git a/dom/xml/crashtests/2073692.html b/dom/xml/crashtests/2073692.html
new file mode 100644
index 00000000000..a46bc060057
--- /dev/null
+++ b/dom/xml/crashtests/2073692.html
@@ -0,0 +1,14 @@
+<html>
+<body>
+<iframe id="f" src="2073692-frame.xml"></iframe>
+<script>
+document.getElementById("f").onload = function() {
+  var xmlDoc = this.contentDocument;
+  var oldRoot = xmlDoc.documentElement;
+  var newRoot = xmlDoc.createElementNS("http://www.w3.org/1999/xhtml", "html");
+  xmlDoc.replaceChild(newRoot, oldRoot);
+  document.documentElement.getBoundingClientRect();
+};
+</script>
+</body>
+</html>
diff --git a/dom/xml/crashtests/crashtests.list b/dom/xml/crashtests/crashtests.list
index bbfd8f3cce3..f53f69d6d69 100644
--- a/dom/xml/crashtests/crashtests.list
+++ b/dom/xml/crashtests/crashtests.list
@@ -13,3 +13,4 @@ load 1038887.xhtml
 load 1192544.xhtml
 load 1405878.xml
 load 1523655.xml
+load 2073692.html
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/dom/xml/crashtests/2073692-frame.xml b/dom/xml/crashtests/2073692-frame.xml
new file mode 100644
index 00000000000..d56986231a9
--- /dev/null
+++ b/dom/xml/crashtests/2073692-frame.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0"?>
+<root>Pretty printed XML</root>
diff --git a/dom/xml/crashtests/2073692.html b/dom/xml/crashtests/2073692.html
new file mode 100644
index 00000000000..a46bc060057
--- /dev/null
+++ b/dom/xml/crashtests/2073692.html
@@ -0,0 +1,14 @@
+<html>
+<body>
+<iframe id="f" src="2073692-frame.xml"></iframe>
+<script>
+document.getElementById("f").onload = function() {
+  var xmlDoc = this.contentDocument;
+  var oldRoot = xmlDoc.documentElement;
+  var newRoot = xmlDoc.createElementNS("http://www.w3.org/1999/xhtml", "html");
+  xmlDoc.replaceChild(newRoot, oldRoot);
+  document.documentElement.getBoundingClientRect();
+};
+</script>
+</body>
+</html>
diff --git a/dom/xml/crashtests/crashtests.list b/dom/xml/crashtests/crashtests.list
index bbfd8f3cce3..f53f69d6d69 100644
--- a/dom/xml/crashtests/crashtests.list
+++ b/dom/xml/crashtests/crashtests.list
@@ -13,3 +13,4 @@ load 1038887.xhtml
 load 1192544.xhtml
 load 1405878.xml
 load 1523655.xml
+load 2073692.html
Loading diff…