Inserting or removing slot elements can cause a crash
authorrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 19 Sep 2015 04:18:27 +0000 (04:18 +0000)
committerrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 19 Sep 2015 04:18:27 +0000 (04:18 +0000)
commitf3764f40a6ab778dc4f8714cb23f2d2e9756405c
treecaa0b149d79491c2de9aade592f5e0245b08e525
parentf3a44f6deeec03f92025fd30fd9f6bd51e552687
Inserting or removing slot elements can cause a crash
https://bugs.webkit.org/show_bug.cgi?id=149365

Reviewed by Antti Koivisto.

Source/WebCore:

HTMLSlotElement::insertedInto and removedFrom were doing completely non-sensical.

Since insertedInto and removedFrom are called on an element whenever it or its ancestor is inserted into
or removed from a container node, we can't always call addSlotElementByName removeSlotElementByName when
those functions are called. Instead, we need to check whether this slot has been inserted into or removed
from a container node that resides inside a shadow root.

Also reverted r189906 since the change was made upon a bogus assumption I had made.

Test: fast/shadow-dom/slot-removal-crash.html

* dom/Element.cpp:
(WebCore::Element::insertedInto): Added comments.
(WebCore::Element::removedFrom): Ditto.
(WebCore::Element::addShadowRoot): Reverted r189906.
(WebCore::Element::removeShadowRoot): Ditto.

* html/HTMLSlotElement.cpp:
(WebCore::HTMLSlotElement::insertedInto): When the insertion point's tree scope is different from ours,
the insertion happened to our shadow host or its ancestor. There is nothing to be done in that case since
the shadow tree was not modified (in particular, our relationship with our shadow root never changed).
We also don't do anything if we got inserted into a parent which is not inside a shadow tree.

(WebCore::HTMLSlotElement::removedFrom): Since Container::removeBetween sets the tree scope before this
function is getting called, we can't compare this element's treeScope with that of the "insertion" point.
They're always different regardless of whether the insertion point was in the same shadow tree to which
we belong or its shadow host's. However, since a node removed from a shadow tree is put into document's
tree scope before this function is called and InShadowTree flag is unset in Node::removedFrom at the end
of this function, this slot element is definitely being removed from its shadow root when isInShadowTree()
is true and the newly set tree scope is of the document. So call removeSlotElementByName if and only if
that condition holds.

(WebCore::HTMLSlotElement::getDistributedNodes): Explicitly check that we're inside a shadow root.

LayoutTests:

Added regression tests.

* fast/shadow-dom/slot-removal-crash.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@190008 268f45cc-cd09-0410-ab3c-d52691b4dbfc
LayoutTests/ChangeLog
LayoutTests/fast/shadow-dom/slot-removal-crash-expected.txt [new file with mode: 0644]
LayoutTests/fast/shadow-dom/slot-removal-crash.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/dom/Element.cpp
Source/WebCore/html/HTMLSlotElement.cpp