Bug 1550881. Prevent document.open() calls from descendant subframes' unload handlers triggered by document.open() from doing anything useful. r=hsivonen
authorBoris Zbarsky <bzbarsky@mit.edu>
Fri, 17 May 2019 12:45:35 +0000
changeset 474549 63a8fe448f092dcf0f5a70d72b27909a8aec6280
parent 474548 158eb97dfd5e6b18f6a13cbf4e648b361deb1a41
child 474550 e57af6316375e40ca67e3af517fc317086c429b3
push id36042
push userdvarga@mozilla.com
push dateTue, 21 May 2019 04:19:40 +0000
treeherdermozilla-central@ca560ff55451 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewershsivonen
bugs1550881
milestone69.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1550881. Prevent document.open() calls from descendant subframes' unload handlers triggered by document.open() from doing anything useful. r=hsivonen Differential Revision: https://phabricator.services.mozilla.com/D30728
dom/html/crashtests/1550881-1.html
dom/html/crashtests/1550881-2.html
dom/html/crashtests/crashtests.list
dom/html/nsHTMLDocument.cpp
new file mode 100644
--- /dev/null
+++ b/dom/html/crashtests/1550881-1.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<iframe srcdoc="<iframe></iframe>"></iframe>
+<script>
+  onload = function() {
+      parent = frames[0];
+      child = parent[0];
+      child.onunload = function() {
+          parent.document.open();
+      }
+      parent.document.open();
+      parent.document.write("Hello");
+  }
+</script>
new file mode 100644
--- /dev/null
+++ b/dom/html/crashtests/1550881-2.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<iframe srcdoc="<iframe></iframe>"></iframe>
+<script>
+  onload = function() {
+      parent = frames[0];
+      child = parent[0];
+      child.onunload = function() {
+          parent.document.open();
+          parent.document.write("Nested");
+      }
+      parent.document.open();
+      parent.document.write("Hello");
+  }
+</script>
--- a/dom/html/crashtests/crashtests.list
+++ b/dom/html/crashtests/crashtests.list
@@ -84,8 +84,10 @@ load 1343886-1.html
 load 1343886-2.xml
 load 1343886-3.xml
 load 1350972.html
 load 1386905.html
 asserts(0-4) load 1401726.html
 load 1412173.html
 load 1440523.html
 load 1547057.html
+load 1550881-1.html
+load 1550881-2.html
--- a/dom/html/nsHTMLDocument.cpp
+++ b/dom/html/nsHTMLDocument.cpp
@@ -1093,17 +1093,25 @@ Document* nsHTMLDocument::Open(const Opt
       if (EventListenerManager* elm =
               nsGlobalWindowInner::Cast(win)->GetExistingListenerManager()) {
         elm->RemoveAllListeners();
       }
     }
   }
 
   // Step 10 -- remove all our DOM kids without firing any mutation events.
-  DisconnectNodeTree();
+  {
+    // We want to ignore any recursive calls to Open() that happen while
+    // disconnecting the node tree.  The spec doesn't say to do this, but the
+    // spec also doesn't envision unload events on subframes firing while we do
+    // this, while all browsers fire them in practice.  See
+    // <https://github.com/whatwg/html/issues/4611>.
+    IgnoreOpensDuringUnload ignoreOpenGuard(this);
+    DisconnectNodeTree();
+  }
 
   // Step 11 -- if we're the current document in our docshell, do the
   // equivalent of pushState() with the new URL we should have.
   if (shell && IsCurrentActiveDocument()) {
     nsCOMPtr<nsIURI> newURI = callerDoc->GetDocumentURI();
     if (callerDoc != this) {
       nsCOMPtr<nsIURI> noFragmentURI;
       nsresult rv = NS_GetURIWithoutRef(newURI, getter_AddRefs(noFragmentURI));