FrameSelection::appearanceUpdateTimerFired should be robust against layout passes...
authorwenson_hsieh@apple.com <wenson_hsieh@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 29 Mar 2018 23:05:06 +0000 (23:05 +0000)
committerwenson_hsieh@apple.com <wenson_hsieh@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 29 Mar 2018 23:05:06 +0000 (23:05 +0000)
https://bugs.webkit.org/show_bug.cgi?id=183395
<rdar://problem/38055732>

Reviewed by Zalan Bujtas.

Source/WebCore:

In the case where a FrameSelection updates its appearance when m_appearanceUpdateTimer is fired, the
FrameSelection's Frame is unprotected, and can be removed by arbitrary script. This patch applies a simple
mitigation by wrapping the Frame in a Ref when firing the appearance update timer, and ensuring that layout is
really up to date before calling updateAppearanceAfterLayoutOrStyleChange() from the timer.

Test: editing/selection/iframe-update-selection-appearance.html

* editing/FrameSelection.cpp:
(WebCore::FrameSelection::appearanceUpdateTimerFired):

LayoutTests:

Add a new layout test that passes if we didn't crash.

* editing/selection/iframe-update-selection-appearance-expected.txt: Added.
* editing/selection/iframe-update-selection-appearance.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@230087 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/editing/selection/iframe-update-selection-appearance-expected.txt [new file with mode: 0644]
LayoutTests/editing/selection/iframe-update-selection-appearance.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/editing/FrameSelection.cpp

index ae998cf..8cb47fc 100644 (file)
@@ -1,3 +1,16 @@
+2018-03-29  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        FrameSelection::appearanceUpdateTimerFired should be robust against layout passes underneath it
+        https://bugs.webkit.org/show_bug.cgi?id=183395
+        <rdar://problem/38055732>
+
+        Reviewed by Zalan Bujtas.
+
+        Add a new layout test that passes if we didn't crash.
+
+        * editing/selection/iframe-update-selection-appearance-expected.txt: Added.
+        * editing/selection/iframe-update-selection-appearance.html: Added.
+
 2018-03-29  Per Arne Vollan  <pvollan@apple.com>
 
         The test http/tests/websocket/tests/hybi/websocket-cookie-overwrite-behavior.html is failing on Windows.
diff --git a/LayoutTests/editing/selection/iframe-update-selection-appearance-expected.txt b/LayoutTests/editing/selection/iframe-update-selection-appearance-expected.txt
new file mode 100644 (file)
index 0000000..43e5eee
--- /dev/null
@@ -0,0 +1,4 @@
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/editing/selection/iframe-update-selection-appearance.html b/LayoutTests/editing/selection/iframe-update-selection-appearance.html
new file mode 100644 (file)
index 0000000..0742a89
--- /dev/null
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <style>
+        body { -webkit-user-modify: read-only; }
+    </style>
+    <script src="../../resources/js-test.js"></script>
+    <script>
+    function reconnectSubframe() {
+        document.body.appendChild(document.querySelector("iframe"));
+    }
+
+    function go() {
+        jsTestIsAsync = true;
+        if (window.finishJSTest)
+            setTimeout(() => setTimeout(finishJSTest));
+
+        getSelection().setPosition(document.body);
+
+        if (window.internals)
+            setTimeout(() => internals.setCaptionsStyleSheetOverride("* { }"));
+
+        reconnectSubframe();
+    }
+    </script>
+</head>
+
+<body onload="go()">
+    <iframe hidden="true"></iframe>
+    <embed type="foobar" onbeforeload="reconnectSubframe()"></embed>
+</body>
+</html>
\ No newline at end of file
index d26a40f..1be68f4 100644 (file)
@@ -1,3 +1,21 @@
+2018-03-29  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        FrameSelection::appearanceUpdateTimerFired should be robust against layout passes underneath it
+        https://bugs.webkit.org/show_bug.cgi?id=183395
+        <rdar://problem/38055732>
+
+        Reviewed by Zalan Bujtas.
+
+        In the case where a FrameSelection updates its appearance when m_appearanceUpdateTimer is fired, the
+        FrameSelection's Frame is unprotected, and can be removed by arbitrary script. This patch applies a simple
+        mitigation by wrapping the Frame in a Ref when firing the appearance update timer, and ensuring that layout is
+        really up to date before calling updateAppearanceAfterLayoutOrStyleChange() from the timer.
+
+        Test: editing/selection/iframe-update-selection-appearance.html
+
+        * editing/FrameSelection.cpp:
+        (WebCore::FrameSelection::appearanceUpdateTimerFired):
+
 2018-03-29  Daniel Bates  <dabates@apple.com>
 
         Substitute ArchiveFactory::isArchiveMIMEType() for ArchiveFactory::isArchiveMimeType().
index bef4dc9..3b4b100 100644 (file)
@@ -2441,6 +2441,10 @@ void FrameSelection::scheduleAppearanceUpdateAfterStyleChange()
 
 void FrameSelection::appearanceUpdateTimerFired()
 {
+    Ref<Frame> protectedFrame(*m_frame);
+    if (auto* document = protectedFrame->document())
+        document->updateLayoutIgnorePendingStylesheets();
+
     updateAppearanceAfterLayoutOrStyleChange();
 }