⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 185838 in webkit


Ignore:
Timestamp:
Jun 22, 2015, 12:35:19 PM (11 years ago)
Author:
Alan Bujtas
Message:

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 "on selection border" and later "inside" 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.
Location:
trunk
Files:
2 added
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r185828 r185838  
     12015-06-22  Zalan Bujtas  <zalan@apple.com>
     2
     3        REGRESSION(r169105) Dangling renderer pointer in SelectionSubtreeRoot::SelectionSubtreeData.
     4        https://bugs.webkit.org/show_bug.cgi?id=146116
     5        rdar://problem/20959369
     6
     7        Reviewed by Brent Fulgham.
     8
     9        This patch ensures that we don't adjust the selection unless the visual selection still matches this subtree root.
     10
     11        When multiple selection roots are present we need to ensure that a RenderObject
     12        only shows up in one of them.
     13        RenderView::splitSelectionBetweenSubtrees(), as the name implies, splits the
     14        selection and sets the selection range (start/end) on each selection root.
     15        However, SelectionSubtreeRoot::adjustForVisibleSelection() later recomputes the range
     16        based on visible selection and that could end up collecting renderers as selection start/end
     17        from another selection subtree.
     18        RenderObject's holds the last selection state (RenderObject::setSelectionState).
     19        If we set a renderer first as "on selection border" and later "inside" using multiple selection roots,
     20        we can't clean up selections properly when this object gets destroyed.
     21        One of the roots ends up with a dangling RenderObject pointer.
     22
     23        * fast/regions/crash-when-renderer-is-in-multiple-selection-subtrees-expected.txt: Added.
     24        * fast/regions/crash-when-renderer-is-in-multiple-selection-subtrees.html: Added.
     25
    1262015-06-22  Daniel Bates  <dabates@apple.com>
    227
  • trunk/Source/WebCore/ChangeLog

    r185834 r185838  
     12015-06-22  Zalan Bujtas  <zalan@apple.com>
     2
     3        REGRESSION(r169105) Dangling renderer pointer in SelectionSubtreeRoot::SelectionSubtreeData.
     4        https://bugs.webkit.org/show_bug.cgi?id=146116
     5        rdar://problem/20959369
     6
     7        Reviewed by Brent Fulgham.
     8
     9        This patch ensures that we don't adjust the selection unless the visual selection still matches this subtree root.
     10
     11        When multiple selection roots are present we need to ensure that a RenderObject
     12        only shows up in one of them.
     13        RenderView::splitSelectionBetweenSubtrees(), as the name implies, splits the
     14        selection and sets the selection range (start/end) on each selection root.
     15        However, SelectionSubtreeRoot::adjustForVisibleSelection() later recomputes the range
     16        based on visible selection and that could end up collecting renderers as selection start/end
     17        from another selection subtree.
     18        RenderObject's holds the last selection state (RenderObject::setSelectionState).
     19        If we set a renderer first as "on selection border" and later "inside" using multiple selection roots,
     20        we can't clean up selections properly when this object gets destroyed.
     21        One of the roots ends up with a dangling RenderObject pointer.
     22
     23        Test: fast/regions/crash-when-renderer-is-in-multiple-selection-subtrees.html
     24
     25        * rendering/SelectionSubtreeRoot.cpp:
     26        (WebCore::SelectionSubtreeRoot::adjustForVisibleSelection):
     27
    1282015-06-22  Jeremy Jones  <jeremyj@apple.com>
    229
  • trunk/Source/WebCore/rendering/SelectionSubtreeRoot.cpp

    r183158 r185838  
    7171    m_selectionSubtreeData.clearSelection();
    7272
    73     if (startPos.isNotNull()
    74         && endPos.isNotNull()
    75         && selection.visibleStart() != selection.visibleEnd()
    76         && startPos.deprecatedNode()->renderer()->flowThreadContainingBlock() == endPos.deprecatedNode()->renderer()->flowThreadContainingBlock()) {
    77         m_selectionSubtreeData.setSelectionStart(startPos.deprecatedNode()->renderer());
    78         m_selectionSubtreeData.setSelectionStartPos(startPos.deprecatedEditingOffset());
    79         m_selectionSubtreeData.setSelectionEnd(endPos.deprecatedNode()->renderer());
    80         m_selectionSubtreeData.setSelectionEndPos(endPos.deprecatedEditingOffset());
    81     }
     73    if (startPos.isNull() || endPos.isNull())
     74        return;
     75
     76    if (selection.visibleStart() == selection.visibleEnd())
     77        return;
     78
     79    if (startPos.deprecatedNode()->renderer()->flowThreadContainingBlock() != endPos.deprecatedNode()->renderer()->flowThreadContainingBlock())
     80        return;
     81
     82    if (&startPos.deprecatedNode()->renderer()->selectionRoot() != this)
     83        return;
     84
     85    m_selectionSubtreeData.setSelectionStart(startPos.deprecatedNode()->renderer());
     86    m_selectionSubtreeData.setSelectionStartPos(startPos.deprecatedEditingOffset());
     87    m_selectionSubtreeData.setSelectionEnd(endPos.deprecatedNode()->renderer());
     88    m_selectionSubtreeData.setSelectionEndPos(endPos.deprecatedEditingOffset());
    8289}
    8390
Note: See TracChangeset for help on using the changeset viewer.