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

Changeset 274862 in webkit


Ignore:
Timestamp:
Mar 23, 2021, 6:36:58 AM (5 years ago)
Author:
commit-queue@webkit.org
Message:

Nullptr crash in HTMLConverter::convert
https://bugs.webkit.org/show_bug.cgi?id=221719

Patch by Frédéric Wang <fwang@igalia.com> on 2021-03-23
Reviewed by Ryosuke Niwa.

When the "Undo" command is called after DOM changes, one of the selection's position anchors
may have been moved to a new document. In that case, just clear the selection. Also add
asserts to ensure the selection is in good state after unapply and reapply commands.

  • editing/CompositeEditCommand.cpp:

(WebCore::EditCommandComposition::unapply): Add security assert to ensure selection is in
good state.
(WebCore::EditCommandComposition::reapply): Ditto.

  • editing/FrameSelection.cpp:

(WebCore::FrameSelection::setSelectionWithoutUpdatingAppearance): If the selection's
position anchors have been moved to a new document then just clear the selection.
(WebCore::FrameSelection::isConnectedToDocument const): New method to verify that all the
positions of the visible selection are in m_document.

  • editing/FrameSelection.h: Declare new method.
  • editing/VisibleSelection.cpp:

(WebCore::VisibleSelection::document const): New method that returns a common document for
all positions or nullptr otherwise.

  • editing/VisibleSelection.h: Declare new method.
Location:
trunk/Source/WebCore
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r274861 r274862  
     12021-03-23  Frédéric Wang  <fwang@igalia.com>
     2
     3        Nullptr crash in HTMLConverter::convert
     4        https://bugs.webkit.org/show_bug.cgi?id=221719
     5
     6        Reviewed by Ryosuke Niwa.
     7
     8        When the "Undo" command is called after DOM changes, one of the selection's position anchors
     9        may have been moved to a new document. In that case, just clear the selection. Also add
     10        asserts to ensure the selection is in good state after unapply and reapply commands.
     11
     12        * editing/CompositeEditCommand.cpp:
     13        (WebCore::EditCommandComposition::unapply): Add security assert to ensure selection is in
     14        good state.
     15        (WebCore::EditCommandComposition::reapply): Ditto.
     16        * editing/FrameSelection.cpp:
     17        (WebCore::FrameSelection::setSelectionWithoutUpdatingAppearance): If the selection's
     18        position anchors have been moved to a new document then just clear the selection.
     19        (WebCore::FrameSelection::isConnectedToDocument const): New method to verify that all the
     20        positions of the visible selection are in m_document.
     21        * editing/FrameSelection.h: Declare new method.
     22        * editing/VisibleSelection.cpp:
     23        (WebCore::VisibleSelection::document const): New method that returns a common document for
     24        all positions or nullptr otherwise.
     25        * editing/VisibleSelection.h: Declare new method.
     26
    1272021-03-23  Kimmo Kinnunen  <kkinnunen@apple.com>
    228
  • trunk/Source/WebCore/editing/CompositeEditCommand.cpp

    r274626 r274862  
    244244    if (AXObjectCache::accessibilityEnabled())
    245245        m_replacedText.postTextStateChangeNotificationForUnapply(m_document->existingAXObjectCache());
     246
     247    RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(m_document->selection().isNone() || m_document->selection().isConnectedToDocument());
    246248}
    247249
     
    271273    if (AXObjectCache::accessibilityEnabled())
    272274        m_replacedText.postTextStateChangeNotificationForReapply(m_document->existingAXObjectCache());
     275
     276    RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(m_document->selection().isNone() || m_document->selection().isConnectedToDocument());
    273277}
    274278
  • trunk/Source/WebCore/editing/FrameSelection.cpp

    r274526 r274862  
    370370        }
    371371
     372        bool selectionEndpointsBelongToMultipleDocuments = newSelection.base().document() && !newSelection.document();
     373        bool selectionIsInAnotherDocument = newSelection.document() && newSelection.document() != m_document.get();
     374        if (selectionEndpointsBelongToMultipleDocuments || selectionIsInAnotherDocument) {
     375            clear();
     376            return false;
     377        }
     378
    372379        if (closeTyping)
    373380            TypingCommand::closeTyping(*m_document);
     
    27952802}
    27962803
     2804bool FrameSelection::isConnectedToDocument() const
     2805{
     2806    return selection().document() == m_document.get();
     2807}
     2808
    27972809RefPtr<Range> FrameSelection::associatedLiveRange()
    27982810{
  • trunk/Source/WebCore/editing/FrameSelection.h

    r274526 r274862  
    253253
    254254    bool isInDocumentTree() const;
     255    bool isConnectedToDocument() const;
     256
    255257    RefPtr<Range> associatedLiveRange();
    256258    void associateLiveRange(Range&);
  • trunk/Source/WebCore/editing/VisibleSelection.cpp

    r272928 r274862  
    143143        return true;
    144144    return false;
     145}
     146
     147RefPtr<Document> VisibleSelection::document() const
     148{
     149    auto baseDocument = makeRefPtr(m_base.document());
     150    if (!baseDocument)
     151        return nullptr;
     152
     153    if (m_extent.document() != baseDocument.get() || m_start.document() != baseDocument.get() || m_end.document() != baseDocument.get())
     154        return nullptr;
     155
     156    if (baseDocument->settings().liveRangeSelectionEnabled() && (m_anchor.document() != baseDocument.get() || m_focus.document() != baseDocument.get()))
     157        return nullptr;
     158
     159    return baseDocument;
    145160}
    146161
  • trunk/Source/WebCore/editing/VisibleSelection.h

    r272928 r274862  
    8888    bool isNoneOrOrphaned() const { return isNone() || start().isOrphan() || end().isOrphan(); }
    8989    bool isOrphan() const;
     90    RefPtr<Document> document() const;
    9091
    9192    bool isBaseFirst() const { return m_anchorIsFirst; }
Note: See TracChangeset for help on using the changeset viewer.