Bug 1385272 - Make plaintext serializer not crash when a <tr> is a child of a <tr>. r=Ehsan
authorHenri Sivonen <hsivonen@hsivonen.fi>
Mon, 14 Aug 2017 14:24:51 +0300
changeset 374811 661723c4cd4567ecaca7e1035cf78e3d29985f90
parent 374810 76eecfca4bc68248176e48a63efd147e16ec135d
child 374812 420253115f0666ea0cb65a7b98dc752c1d1f9b91
push id48808
push userhsivonen@mozilla.com
push dateTue, 15 Aug 2017 14:31:14 +0000
treeherderautoland@661723c4cd45 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersEhsan
bugs1385272
milestone57.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 1385272 - Make plaintext serializer not crash when a <tr> is a child of a <tr>. r=Ehsan MozReview-Commit-ID: CMNIWYX8R07
dom/base/crashtests/1385272-1.html
dom/base/crashtests/crashtests.list
dom/base/nsDocumentEncoder.cpp
new file mode 100644
--- /dev/null
+++ b/dom/base/crashtests/1385272-1.html
@@ -0,0 +1,29 @@
+<html>
+    <head>
+       <script>
+            try { o1 = document.createElement("tr") } catch(e) { }
+            try { o2 = document.createElement("td") } catch(e) { }
+            try { o3 = document.createElement("tr") } catch(e) { }
+            try { o4 = document.createElement("div") } catch(e) { }
+            try { o5 = document.createElement("input") } catch(e) { }
+            try { o6 = document.createElement('map') } catch(e) { }
+            try { o7 = document.createElement('select') } catch(e) { }
+            try { o8 = document.createElement("canvas") } catch(e) { }
+            try { o9 = document.createElement("area") } catch(e) { };
+            try { o1.appendChild(o2) } catch(e) { }
+            try { document.documentElement.appendChild(o3)  } catch(e) { }
+            try { document.documentElement.appendChild(o4)  } catch(e) { }
+            try { document.documentElement.appendChild(o6) } catch(e) { }
+            try { o3.appendChild(o7) } catch(e) { }
+            try { o4.appendChild(o8) } catch(e) { }
+            try { o3.appendChild(o5); } catch(e) { }
+            try { o3.appendChild(o1); } catch(e) { }
+            try { o6.contentEditable = "true" } catch(e) { };
+            try { o6.offsetHeight } catch(e) { };
+            try { o4.appendChild(o9) } catch(e) { };
+            try { o2.insertAdjacentHTML("beforeBegin", "<button id='id0'></button>\n"); } catch(e) { }
+            try { document.replaceChild(document.documentElement, document.documentElement); } catch(e) { }
+            try { document.execCommand("selectall",false,null) } catch(e) { }
+        </script>
+    </head>
+</html>
--- a/dom/base/crashtests/crashtests.list
+++ b/dom/base/crashtests/crashtests.list
@@ -216,8 +216,9 @@ pref(clipboard.autocopy,true) load 13707
 pref(dom.IntersectionObserver.enabled,true) load 1370968.html
 load 1377826.html
 skip-if(stylo&&isDebugBuild&&winWidget) load structured_clone_container_throws.html # Bug 1383845
 HTTP(..) load xhr_abortinprogress.html
 load xhr_empty_datauri.html
 load xhr_html_nullresponse.html
 load 1383478.html
 load 1383780.html
+pref(clipboard.autocopy,true) load 1385272-1.html
--- a/dom/base/nsDocumentEncoder.cpp
+++ b/dom/base/nsDocumentEncoder.cpp
@@ -1013,16 +1013,24 @@ nsDocumentEncoder::Clear()
 }
 
 NS_IMETHODIMP
 nsDocumentEncoder::EncodeToString(nsAString& aOutputString)
 {
   return EncodeToStringWithMaxLength(0, aOutputString);
 }
 
+static bool ParentIsTR(nsIContent* aContent) {
+  mozilla::dom::Element* parent = aContent->GetParentElement();
+  if (!parent) {
+    return false;
+  }
+  return parent->IsHTMLElement(nsGkAtoms::tr);
+}
+
 NS_IMETHODIMP
 nsDocumentEncoder::EncodeToStringWithMaxLength(uint32_t aMaxLength,
                                                nsAString& aOutputString)
 {
   if (!mDocument)
     return NS_ERROR_NOT_INITIALIZED;
 
   AutoReleaseDocumentIfNeeded autoReleaseDocument(this);
@@ -1083,17 +1091,17 @@ nsDocumentEncoder::EncodeToStringWithMax
       if (node != prevNode) {
         nsCOMPtr<nsINode> p;
         if (prevNode) {
           p = do_QueryInterface(prevNode);
           rv = SerializeNodeEnd(p, output);
           NS_ENSURE_SUCCESS(rv, rv);
         }
         nsCOMPtr<nsIContent> content = do_QueryInterface(node);
-        if (content && content->IsHTMLElement(nsGkAtoms::tr)) {
+        if (content && content->IsHTMLElement(nsGkAtoms::tr) && !ParentIsTR(content)) {
           nsINode* n = content;
           if (!prevNode) {
             // Went from a non-<tr> to a <tr>
             mCommonAncestors.Clear();
             nsContentUtils::GetAncestors(n->GetParentNode(), mCommonAncestors);
             rv = SerializeRangeContextStart(mCommonAncestors, output);
             NS_ENSURE_SUCCESS(rv, rv);
             // Don't let SerializeRangeToString serialize the context again