<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[185838] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/185838">185838</a></dd>
<dt>Author</dt> <dd>zalan@apple.com</dd>
<dt>Date</dt> <dd>2015-06-22 12:35:19 -0700 (Mon, 22 Jun 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>REGRESSION(<a href="http://trac.webkit.org/projects/webkit/changeset/169105">r169105</a>) Dangling renderer pointer in SelectionSubtreeRoot::SelectionSubtreeData.
https://bugs.webkit.org/show_bug.cgi?id=146116
rdar://problem/20959369

Reviewed by Brent Fulgham.

This patch ensures that we don't adjust the selection unless the visual selection still matches this subtree root.

When multiple selection roots are present we need to ensure that a RenderObject
only shows up in one of them.
RenderView::splitSelectionBetweenSubtrees(), as the name implies, splits the
selection and sets the selection range (start/end) on each selection root.
However, SelectionSubtreeRoot::adjustForVisibleSelection() later recomputes the range
based on visible selection and that could end up collecting renderers as selection start/end
from another selection subtree.
RenderObject's holds the last selection state (RenderObject::setSelectionState).
If we set a renderer first as &quot;on selection border&quot; and later &quot;inside&quot; using multiple selection roots,
we can't clean up selections properly when this object gets destroyed.
One of the roots ends up with a dangling RenderObject pointer.

Source/WebCore:

Test: fast/regions/crash-when-renderer-is-in-multiple-selection-subtrees.html

* rendering/SelectionSubtreeRoot.cpp:
(WebCore::SelectionSubtreeRoot::adjustForVisibleSelection):

LayoutTests:

* fast/regions/crash-when-renderer-is-in-multiple-selection-subtrees-expected.txt: Added.
* fast/regions/crash-when-renderer-is-in-multiple-selection-subtrees.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorerenderingSelectionSubtreeRootcpp">trunk/Source/WebCore/rendering/SelectionSubtreeRoot.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsfastregionscrashwhenrendererisinmultipleselectionsubtreesexpectedtxt">trunk/LayoutTests/fast/regions/crash-when-renderer-is-in-multiple-selection-subtrees-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastregionscrashwhenrendererisinmultipleselectionsubtreeshtml">trunk/LayoutTests/fast/regions/crash-when-renderer-is-in-multiple-selection-subtrees.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (185837 => 185838)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2015-06-22 19:30:46 UTC (rev 185837)
+++ trunk/LayoutTests/ChangeLog        2015-06-22 19:35:19 UTC (rev 185838)
</span><span class="lines">@@ -1,3 +1,28 @@
</span><ins>+2015-06-22  Zalan Bujtas  &lt;zalan@apple.com&gt;
+
+        REGRESSION(r169105) Dangling renderer pointer in SelectionSubtreeRoot::SelectionSubtreeData.
+        https://bugs.webkit.org/show_bug.cgi?id=146116
+        rdar://problem/20959369
+
+        Reviewed by Brent Fulgham.
+
+        This patch ensures that we don't adjust the selection unless the visual selection still matches this subtree root.
+
+        When multiple selection roots are present we need to ensure that a RenderObject
+        only shows up in one of them.
+        RenderView::splitSelectionBetweenSubtrees(), as the name implies, splits the
+        selection and sets the selection range (start/end) on each selection root.
+        However, SelectionSubtreeRoot::adjustForVisibleSelection() later recomputes the range
+        based on visible selection and that could end up collecting renderers as selection start/end
+        from another selection subtree.
+        RenderObject's holds the last selection state (RenderObject::setSelectionState).
+        If we set a renderer first as &quot;on selection border&quot; and later &quot;inside&quot; using multiple selection roots,
+        we can't clean up selections properly when this object gets destroyed.
+        One of the roots ends up with a dangling RenderObject pointer.
+
+        * fast/regions/crash-when-renderer-is-in-multiple-selection-subtrees-expected.txt: Added.
+        * fast/regions/crash-when-renderer-is-in-multiple-selection-subtrees.html: Added.
+
</ins><span class="cx"> 2015-06-22  Daniel Bates  &lt;dabates@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         AX: UI Automation cannot find AutoFill or search cancel buttons
</span></span></pre></div>
<a id="trunkLayoutTestsfastregionscrashwhenrendererisinmultipleselectionsubtreesexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/regions/crash-when-renderer-is-in-multiple-selection-subtrees-expected.txt (0 => 185838)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/regions/crash-when-renderer-is-in-multiple-selection-subtrees-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/regions/crash-when-renderer-is-in-multiple-selection-subtrees-expected.txt        2015-06-22 19:35:19 UTC (rev 185838)
</span><span class="lines">@@ -0,0 +1,4 @@
</span><ins>+foo
+Pass if no crash or assert in debug.
+foobar
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfastregionscrashwhenrendererisinmultipleselectionsubtreeshtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/regions/crash-when-renderer-is-in-multiple-selection-subtrees.html (0 => 185838)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/regions/crash-when-renderer-is-in-multiple-selection-subtrees.html                                (rev 0)
+++ trunk/LayoutTests/fast/regions/crash-when-renderer-is-in-multiple-selection-subtrees.html        2015-06-22 19:35:19 UTC (rev 185838)
</span><span class="lines">@@ -0,0 +1,19 @@
</span><ins>+&lt;html id=&quot;webtest0&quot;&gt;
+&lt;head&gt;
+&lt;style&gt;
+        :last-child { -webkit-flow-into: foo; }
+&lt;/style&gt;
+
+&lt;script&gt;
+    if (window.testRunner)
+        testRunner.dumpAsText();
+    document.write(&quot;foo&lt;br&gt;&quot;);
+&lt;/script&gt;
+&lt;/head&gt;
+&lt;body&gt;Pass if no crash or assert in debug.&lt;summary id=&quot;webtest5&quot;&gt;&lt;mathml&gt;&lt;femerge&gt;&lt;/femerge&gt;&lt;/mathml&gt;foobar&lt;table&gt;&lt;/table&gt;&lt;/summary&gt;&lt;/body&gt;
+&lt;script&gt;
+document.querySelector(&quot;#webtest0&quot;).appendChild(document.createElement(&quot;canvas&quot;));
+document.execCommand(&quot;SelectAll&quot;);
+document.getElementById(&quot;webtest5&quot;).appendChild(document.createElement(&quot;feconvolvematrix&quot;));
+&lt;/script&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (185837 => 185838)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-06-22 19:30:46 UTC (rev 185837)
+++ trunk/Source/WebCore/ChangeLog        2015-06-22 19:35:19 UTC (rev 185838)
</span><span class="lines">@@ -1,3 +1,30 @@
</span><ins>+2015-06-22  Zalan Bujtas  &lt;zalan@apple.com&gt;
+
+        REGRESSION(r169105) Dangling renderer pointer in SelectionSubtreeRoot::SelectionSubtreeData.
+        https://bugs.webkit.org/show_bug.cgi?id=146116
+        rdar://problem/20959369
+
+        Reviewed by Brent Fulgham.
+
+        This patch ensures that we don't adjust the selection unless the visual selection still matches this subtree root.
+
+        When multiple selection roots are present we need to ensure that a RenderObject
+        only shows up in one of them.
+        RenderView::splitSelectionBetweenSubtrees(), as the name implies, splits the
+        selection and sets the selection range (start/end) on each selection root.
+        However, SelectionSubtreeRoot::adjustForVisibleSelection() later recomputes the range
+        based on visible selection and that could end up collecting renderers as selection start/end
+        from another selection subtree.
+        RenderObject's holds the last selection state (RenderObject::setSelectionState).
+        If we set a renderer first as &quot;on selection border&quot; and later &quot;inside&quot; using multiple selection roots,
+        we can't clean up selections properly when this object gets destroyed.
+        One of the roots ends up with a dangling RenderObject pointer.
+
+        Test: fast/regions/crash-when-renderer-is-in-multiple-selection-subtrees.html
+
+        * rendering/SelectionSubtreeRoot.cpp:
+        (WebCore::SelectionSubtreeRoot::adjustForVisibleSelection):
+
</ins><span class="cx"> 2015-06-22  Jeremy Jones  &lt;jeremyj@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Do not exit fullscreen when starting PiP since this is done automatically.
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingSelectionSubtreeRootcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/SelectionSubtreeRoot.cpp (185837 => 185838)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/SelectionSubtreeRoot.cpp        2015-06-22 19:30:46 UTC (rev 185837)
+++ trunk/Source/WebCore/rendering/SelectionSubtreeRoot.cpp        2015-06-22 19:35:19 UTC (rev 185838)
</span><span class="lines">@@ -70,15 +70,22 @@
</span><span class="cx"> 
</span><span class="cx">     m_selectionSubtreeData.clearSelection();
</span><span class="cx"> 
</span><del>-    if (startPos.isNotNull()
-        &amp;&amp; endPos.isNotNull()
-        &amp;&amp; selection.visibleStart() != selection.visibleEnd()
-        &amp;&amp; startPos.deprecatedNode()-&gt;renderer()-&gt;flowThreadContainingBlock() == endPos.deprecatedNode()-&gt;renderer()-&gt;flowThreadContainingBlock()) {
-        m_selectionSubtreeData.setSelectionStart(startPos.deprecatedNode()-&gt;renderer());
-        m_selectionSubtreeData.setSelectionStartPos(startPos.deprecatedEditingOffset());
-        m_selectionSubtreeData.setSelectionEnd(endPos.deprecatedNode()-&gt;renderer());
-        m_selectionSubtreeData.setSelectionEndPos(endPos.deprecatedEditingOffset());
-    }
</del><ins>+    if (startPos.isNull() || endPos.isNull())
+        return;
+
+    if (selection.visibleStart() == selection.visibleEnd())
+        return;
+
+    if (startPos.deprecatedNode()-&gt;renderer()-&gt;flowThreadContainingBlock() != endPos.deprecatedNode()-&gt;renderer()-&gt;flowThreadContainingBlock())
+        return;
+
+    if (&amp;startPos.deprecatedNode()-&gt;renderer()-&gt;selectionRoot() != this)
+        return;
+
+    m_selectionSubtreeData.setSelectionStart(startPos.deprecatedNode()-&gt;renderer());
+    m_selectionSubtreeData.setSelectionStartPos(startPos.deprecatedEditingOffset());
+    m_selectionSubtreeData.setSelectionEnd(endPos.deprecatedNode()-&gt;renderer());
+    m_selectionSubtreeData.setSelectionEndPos(endPos.deprecatedEditingOffset());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre>
</div>
</div>

</body>
</html>