Title: [218583] releases/WebKitGTK/webkit-2.16
Revision
218583
Author
[email protected]
Date
2017-06-20 03:34:31 -0700 (Tue, 20 Jun 2017)

Log Message

Merge r218451 - Crash due to infinite recursion via FrameSelection::updateAppearanceAfterLayout
https://bugs.webkit.org/show_bug.cgi?id=173468

Reviewed by Ryosuke Niwa.

Source/WebCore:

Test: editing/selection/updateAppearanceAfterLayout-recursion.html

Calling FrameSelection::updateAppearanceAfterLayout() from Document::resolveStyle is unsafe
because it may cause another call to resolveStyle. We have some cases where the style
is still unclean when updateAppearanceAfterLayout() is called. This can lead to infinite
recursion.

The test case is not the common stack seen in CrashTracer (couldn't quit replicate it) but
the updateAppearanceAfterLayout/resolveStyle recursion is the same.

* dom/Document.cpp:
(WebCore::Document::resolveStyle):

    Normally selection appearance update is done in post-layout but not all style resolutions schedule a layout.
    Invoke it asynchronously in that case instead of the previous synchronous call.

* editing/FrameSelection.cpp:
(WebCore::FrameSelection::FrameSelection):
(WebCore::FrameSelection::updateAppearanceAfterLayout):
(WebCore::FrameSelection::scheduleAppearanceUpdateAfterStyleChange):
(WebCore::FrameSelection::appearanceUpdateTimerFired):
(WebCore::FrameSelection::updateAppearanceAfterLayoutOrStyleChange):
* editing/FrameSelection.h:

LayoutTests:

* editing/selection/updateAppearanceAfterLayout-recursion-expected.txt: Added.
* editing/selection/updateAppearanceAfterLayout-recursion.html: Added.

Modified Paths

Added Paths

Diff

Modified: releases/WebKitGTK/webkit-2.16/LayoutTests/ChangeLog (218582 => 218583)


--- releases/WebKitGTK/webkit-2.16/LayoutTests/ChangeLog	2017-06-20 10:29:53 UTC (rev 218582)
+++ releases/WebKitGTK/webkit-2.16/LayoutTests/ChangeLog	2017-06-20 10:34:31 UTC (rev 218583)
@@ -1,3 +1,13 @@
+2017-06-17  Antti Koivisto  <[email protected]>
+
+        Crash due to infinite recursion via FrameSelection::updateAppearanceAfterLayout
+        https://bugs.webkit.org/show_bug.cgi?id=173468
+
+        Reviewed by Ryosuke Niwa.
+
+        * editing/selection/updateAppearanceAfterLayout-recursion-expected.txt: Added.
+        * editing/selection/updateAppearanceAfterLayout-recursion.html: Added.
+
 2017-06-17  Ryosuke Niwa  <[email protected]>
 
         REGRESSION(r209495): materiauxlaverdure.com fails to load

Added: releases/WebKitGTK/webkit-2.16/LayoutTests/editing/selection/updateAppearanceAfterLayout-recursion-expected.txt (0 => 218583)


--- releases/WebKitGTK/webkit-2.16/LayoutTests/editing/selection/updateAppearanceAfterLayout-recursion-expected.txt	                        (rev 0)
+++ releases/WebKitGTK/webkit-2.16/LayoutTests/editing/selection/updateAppearanceAfterLayout-recursion-expected.txt	2017-06-20 10:34:31 UTC (rev 218583)
@@ -0,0 +1,2 @@
+edit
+target

Added: releases/WebKitGTK/webkit-2.16/LayoutTests/editing/selection/updateAppearanceAfterLayout-recursion.html (0 => 218583)


--- releases/WebKitGTK/webkit-2.16/LayoutTests/editing/selection/updateAppearanceAfterLayout-recursion.html	                        (rev 0)
+++ releases/WebKitGTK/webkit-2.16/LayoutTests/editing/selection/updateAppearanceAfterLayout-recursion.html	2017-06-20 10:34:31 UTC (rev 218583)
@@ -0,0 +1,17 @@
+<script>
+if (window.testRunner) {
+    internals.settings.setTelephoneNumberParsingEnabled(true);
+    testRunner.dumpAsText();
+}
+</script>
+<div id=edit>edit</div>
+<div id=target>target</div>
+<script>
+window.getSelection().selectAllChildren(edit);
+target.offsetWidth;
+const link = document.createElement("link");
+link.setAttribute("rel", "stylesheet");
+link.setAttribute("href", "data:text/css,"+Math.random());
+document.head.appendChild(link);
+location.hash = "#target";
+</script>

Modified: releases/WebKitGTK/webkit-2.16/Source/WebCore/ChangeLog (218582 => 218583)


--- releases/WebKitGTK/webkit-2.16/Source/WebCore/ChangeLog	2017-06-20 10:29:53 UTC (rev 218582)
+++ releases/WebKitGTK/webkit-2.16/Source/WebCore/ChangeLog	2017-06-20 10:34:31 UTC (rev 218583)
@@ -1,3 +1,34 @@
+2017-06-17  Antti Koivisto  <[email protected]>
+
+        Crash due to infinite recursion via FrameSelection::updateAppearanceAfterLayout
+        https://bugs.webkit.org/show_bug.cgi?id=173468
+
+        Reviewed by Ryosuke Niwa.
+
+        Test: editing/selection/updateAppearanceAfterLayout-recursion.html
+
+        Calling FrameSelection::updateAppearanceAfterLayout() from Document::resolveStyle is unsafe
+        because it may cause another call to resolveStyle. We have some cases where the style
+        is still unclean when updateAppearanceAfterLayout() is called. This can lead to infinite
+        recursion.
+
+        The test case is not the common stack seen in CrashTracer (couldn't quit replicate it) but
+        the updateAppearanceAfterLayout/resolveStyle recursion is the same.
+
+        * dom/Document.cpp:
+        (WebCore::Document::resolveStyle):
+
+            Normally selection appearance update is done in post-layout but not all style resolutions schedule a layout.
+            Invoke it asynchronously in that case instead of the previous synchronous call.
+
+        * editing/FrameSelection.cpp:
+        (WebCore::FrameSelection::FrameSelection):
+        (WebCore::FrameSelection::updateAppearanceAfterLayout):
+        (WebCore::FrameSelection::scheduleAppearanceUpdateAfterStyleChange):
+        (WebCore::FrameSelection::appearanceUpdateTimerFired):
+        (WebCore::FrameSelection::updateAppearanceAfterLayoutOrStyleChange):
+        * editing/FrameSelection.h:
+
 2017-06-17  Ryosuke Niwa  <[email protected]>
 
         REGRESSION(r209495): materiauxlaverdure.com fails to load

Modified: releases/WebKitGTK/webkit-2.16/Source/WebCore/dom/Document.cpp (218582 => 218583)


--- releases/WebKitGTK/webkit-2.16/Source/WebCore/dom/Document.cpp	2017-06-20 10:29:53 UTC (rev 218582)
+++ releases/WebKitGTK/webkit-2.16/Source/WebCore/dom/Document.cpp	2017-06-20 10:34:31 UTC (rev 218583)
@@ -1834,8 +1834,9 @@
     if (updatedCompositingLayers && !frameView.needsLayout())
         frameView.viewportContentsChanged();
 
+    // Usually this is handled by post-layout.
     if (!frameView.needsLayout())
-        frameView.frame().selection().updateAppearanceAfterLayout();
+        frameView.frame().selection().scheduleAppearanceUpdateAfterStyleChange();
 
     // As a result of the style recalculation, the currently hovered element might have been
     // detached (for example, by setting display:none in the :hover style), schedule another mouseMove event
@@ -1845,6 +1846,8 @@
 
     if (m_gotoAnchorNeededAfterStylesheetsLoad && !styleScope().hasPendingSheets())
         frameView.scrollToFragment(m_url);
+
+    // FIXME: Ideally we would ASSERT(!needsStyleRecalc()) here but we have some cases where it is not true.
 }
 
 bool Document::needsStyleRecalc() const

Modified: releases/WebKitGTK/webkit-2.16/Source/WebCore/editing/FrameSelection.cpp (218582 => 218583)


--- releases/WebKitGTK/webkit-2.16/Source/WebCore/editing/FrameSelection.cpp	2017-06-20 10:29:53 UTC (rev 218582)
+++ releases/WebKitGTK/webkit-2.16/Source/WebCore/editing/FrameSelection.cpp	2017-06-20 10:34:31 UTC (rev 218583)
@@ -111,6 +111,7 @@
     , m_xPosForVerticalArrowNavigation(NoXPosForVerticalArrowNavigation())
     , m_granularity(CharacterGranularity)
     , m_caretBlinkTimer(*this, &FrameSelection::caretBlinkTimerFired)
+    , m_appearanceUpdateTimer(*this, &FrameSelection::appearanceUpdateTimerFired)
     , m_caretInsidePositionFixed(false)
     , m_absCaretBoundsDirty(true)
     , m_caretPaint(true)
@@ -2397,6 +2398,22 @@
 
 void FrameSelection::updateAppearanceAfterLayout()
 {
+    m_appearanceUpdateTimer.stop();
+    updateAppearanceAfterLayoutOrStyleChange();
+}
+
+void FrameSelection::scheduleAppearanceUpdateAfterStyleChange()
+{
+    m_appearanceUpdateTimer.startOneShot(0_s);
+}
+
+void FrameSelection::appearanceUpdateTimerFired()
+{
+    updateAppearanceAfterLayoutOrStyleChange();
+}
+
+void FrameSelection::updateAppearanceAfterLayoutOrStyleChange()
+{
     if (auto* client = m_frame->editor().client())
         client->updateEditorStateAfterLayoutIfEditabilityChanged();
 

Modified: releases/WebKitGTK/webkit-2.16/Source/WebCore/editing/FrameSelection.h (218582 => 218583)


--- releases/WebKitGTK/webkit-2.16/Source/WebCore/editing/FrameSelection.h	2017-06-20 10:29:53 UTC (rev 218582)
+++ releases/WebKitGTK/webkit-2.16/Source/WebCore/editing/FrameSelection.h	2017-06-20 10:34:31 UTC (rev 218583)
@@ -151,6 +151,7 @@
     void prepareForDestruction();
 
     void updateAppearanceAfterLayout();
+    void scheduleAppearanceUpdateAfterStyleChange();
     void setNeedsSelectionUpdate();
 
     bool contains(const LayoutPoint&);
@@ -315,6 +316,9 @@
 
     void caretBlinkTimerFired();
 
+    void updateAppearanceAfterLayoutOrStyleChange();
+    void appearanceUpdateTimerFired();
+
     void setCaretVisibility(CaretVisibility);
     bool recomputeCaretRect();
     void invalidateCaretRect();
@@ -334,6 +338,7 @@
     RefPtr<EditingStyle> m_typingStyle;
 
     Timer m_caretBlinkTimer;
+    Timer m_appearanceUpdateTimer;
     // The painted bounds of the caret in absolute coordinates
     IntRect m_absCaretBounds;
     bool m_caretInsidePositionFixed : 1;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to