Title: [274862] trunk/Source/WebCore
Revision
274862
Author
[email protected]
Date
2021-03-23 06:36:58 -0700 (Tue, 23 Mar 2021)

Log Message

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

Patch by Frédéric Wang <[email protected]> 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.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (274861 => 274862)


--- trunk/Source/WebCore/ChangeLog	2021-03-23 13:15:48 UTC (rev 274861)
+++ trunk/Source/WebCore/ChangeLog	2021-03-23 13:36:58 UTC (rev 274862)
@@ -1,3 +1,29 @@
+2021-03-23  Frédéric Wang  <[email protected]>
+
+        Nullptr crash in HTMLConverter::convert
+        https://bugs.webkit.org/show_bug.cgi?id=221719
+
+        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.
+
 2021-03-23  Kimmo Kinnunen  <[email protected]>
 
         REGRESSION(r274860): error: ‘class WebCore::ExtensionsGLOpenGLCommon’ has no member named ‘drawArraysInstancedANGLE’

Modified: trunk/Source/WebCore/editing/CompositeEditCommand.cpp (274861 => 274862)


--- trunk/Source/WebCore/editing/CompositeEditCommand.cpp	2021-03-23 13:15:48 UTC (rev 274861)
+++ trunk/Source/WebCore/editing/CompositeEditCommand.cpp	2021-03-23 13:36:58 UTC (rev 274862)
@@ -243,6 +243,8 @@
 
     if (AXObjectCache::accessibilityEnabled())
         m_replacedText.postTextStateChangeNotificationForUnapply(m_document->existingAXObjectCache());
+
+    RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(m_document->selection().isNone() || m_document->selection().isConnectedToDocument());
 }
 
 void EditCommandComposition::reapply()
@@ -270,6 +272,8 @@
 
     if (AXObjectCache::accessibilityEnabled())
         m_replacedText.postTextStateChangeNotificationForReapply(m_document->existingAXObjectCache());
+
+    RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(m_document->selection().isNone() || m_document->selection().isConnectedToDocument());
 }
 
 void EditCommandComposition::append(SimpleEditCommand* command)

Modified: trunk/Source/WebCore/editing/FrameSelection.cpp (274861 => 274862)


--- trunk/Source/WebCore/editing/FrameSelection.cpp	2021-03-23 13:15:48 UTC (rev 274861)
+++ trunk/Source/WebCore/editing/FrameSelection.cpp	2021-03-23 13:36:58 UTC (rev 274862)
@@ -369,6 +369,13 @@
             return false;
         }
 
+        bool selectionEndpointsBelongToMultipleDocuments = newSelection.base().document() && !newSelection.document();
+        bool selectionIsInAnotherDocument = newSelection.document() && newSelection.document() != m_document.get();
+        if (selectionEndpointsBelongToMultipleDocuments || selectionIsInAnotherDocument) {
+            clear();
+            return false;
+        }
+
         if (closeTyping)
             TypingCommand::closeTyping(*m_document);
 
@@ -2794,6 +2801,11 @@
     return containsEndpoints(m_document, m_selection.range());
 }
 
+bool FrameSelection::isConnectedToDocument() const
+{
+    return selection().document() == m_document.get();
+}
+
 RefPtr<Range> FrameSelection::associatedLiveRange()
 {
     if (!m_associatedLiveRange) {

Modified: trunk/Source/WebCore/editing/FrameSelection.h (274861 => 274862)


--- trunk/Source/WebCore/editing/FrameSelection.h	2021-03-23 13:15:48 UTC (rev 274861)
+++ trunk/Source/WebCore/editing/FrameSelection.h	2021-03-23 13:36:58 UTC (rev 274862)
@@ -252,6 +252,8 @@
     void setShouldShowBlockCursor(bool);
 
     bool isInDocumentTree() const;
+    bool isConnectedToDocument() const;
+
     RefPtr<Range> associatedLiveRange();
     void associateLiveRange(Range&);
     void disassociateLiveRange();

Modified: trunk/Source/WebCore/editing/VisibleSelection.cpp (274861 => 274862)


--- trunk/Source/WebCore/editing/VisibleSelection.cpp	2021-03-23 13:15:48 UTC (rev 274861)
+++ trunk/Source/WebCore/editing/VisibleSelection.cpp	2021-03-23 13:36:58 UTC (rev 274862)
@@ -144,6 +144,21 @@
     return false;
 }
 
+RefPtr<Document> VisibleSelection::document() const
+{
+    auto baseDocument = makeRefPtr(m_base.document());
+    if (!baseDocument)
+        return nullptr;
+
+    if (m_extent.document() != baseDocument.get() || m_start.document() != baseDocument.get() || m_end.document() != baseDocument.get())
+        return nullptr;
+
+    if (baseDocument->settings().liveRangeSelectionEnabled() && (m_anchor.document() != baseDocument.get() || m_focus.document() != baseDocument.get()))
+        return nullptr;
+
+    return baseDocument;
+}
+
 Optional<SimpleRange> VisibleSelection::firstRange() const
 {
     if (isNoneOrOrphaned())

Modified: trunk/Source/WebCore/editing/VisibleSelection.h (274861 => 274862)


--- trunk/Source/WebCore/editing/VisibleSelection.h	2021-03-23 13:15:48 UTC (rev 274861)
+++ trunk/Source/WebCore/editing/VisibleSelection.h	2021-03-23 13:36:58 UTC (rev 274862)
@@ -87,6 +87,7 @@
     bool isNonOrphanedRange() const { return isRange() && !start().isOrphan() && !end().isOrphan(); }
     bool isNoneOrOrphaned() const { return isNone() || start().isOrphan() || end().isOrphan(); }
     bool isOrphan() const;
+    RefPtr<Document> document() const;
 
     bool isBaseFirst() const { return m_anchorIsFirst; }
     bool isDirectional() const { return m_isDirectional; }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to