Bug 1385272 - Make plaintext serializer not crash when a <tr> is a child of a <tr>. r=Ehsan
MozReview-Commit-ID: CMNIWYX8R07
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