[macOS] Dispatching reentrant "contextmenu" events may cause crashes
authorwenson_hsieh@apple.com <wenson_hsieh@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 11 Mar 2019 22:46:32 +0000 (22:46 +0000)
committerwenson_hsieh@apple.com <wenson_hsieh@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 11 Mar 2019 22:46:32 +0000 (22:46 +0000)
https://bugs.webkit.org/show_bug.cgi?id=195571
<rdar://problem/48086046>

Reviewed by Andy Estes.

Source/WebCore:

Make ContextMenuController::handleContextMenuEvent robust against reentrancy by guarding it with a boolean flag.
As demonstrated in the test case, it is currently possible to force WebKit into a bad state by dispatching a
synthetic "contextmenu" event from within the scope of one of the "before(copy|cut|paste)" events triggered as
a result of handling a context menu event.

Test: fast/events/contextmenu-reentrancy-crash.html

* page/ContextMenuController.cpp:
(WebCore::ContextMenuController::handleContextMenuEvent):
* page/ContextMenuController.h:

LayoutTests:

Add a test to verify that triggering reentrant "contextmenu" events from script does not cause a crash.

* fast/events/contextmenu-reentrancy-crash-expected.txt: Added.
* fast/events/contextmenu-reentrancy-crash.html: Added.

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

LayoutTests/ChangeLog
LayoutTests/fast/events/contextmenu-reentrancy-crash-expected.txt [new file with mode: 0644]
LayoutTests/fast/events/contextmenu-reentrancy-crash.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/page/ContextMenuController.cpp
Source/WebCore/page/ContextMenuController.h

index cacc906..d6e90ef 100644 (file)
@@ -1,3 +1,16 @@
+2019-03-11  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        [macOS] Dispatching reentrant "contextmenu" events may cause crashes
+        https://bugs.webkit.org/show_bug.cgi?id=195571
+        <rdar://problem/48086046>
+
+        Reviewed by Andy Estes.
+
+        Add a test to verify that triggering reentrant "contextmenu" events from script does not cause a crash.
+
+        * fast/events/contextmenu-reentrancy-crash-expected.txt: Added.
+        * fast/events/contextmenu-reentrancy-crash.html: Added.
+
 2019-03-11  Truitt Savell  <tsavell@apple.com>
 
         REGRESSION: Layout Test media/media-fullscreen-return-to-inline.html is a flaky timeout
diff --git a/LayoutTests/fast/events/contextmenu-reentrancy-crash-expected.txt b/LayoutTests/fast/events/contextmenu-reentrancy-crash-expected.txt
new file mode 100644 (file)
index 0000000..53e94be
--- /dev/null
@@ -0,0 +1,3 @@
+This test verifies that we don't crash when attempting to handle "contextmenu" events in a reentrant manner. This test passes if the green text "PASS" is present after page load.
+
+PASS
diff --git a/LayoutTests/fast/events/contextmenu-reentrancy-crash.html b/LayoutTests/fast/events/contextmenu-reentrancy-crash.html
new file mode 100644 (file)
index 0000000..b91fccf
--- /dev/null
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<body>
+<p>This test verifies that we don't crash when attempting to handle "contextmenu" events in a reentrant manner. This test passes if the green text "PASS" is present after page load.</p>
+</body>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+
+function dispatchContextMenuEvent() {
+    document.body.dispatchEvent(new MouseEvent("contextmenu"));
+}
+
+document.designMode = "on";
+document.addEventListener("beforepaste", dispatchContextMenuEvent);
+dispatchContextMenuEvent();
+document.writeln("<pre style='color: green'>PASS</pre>");
+</script>
+</html>
index f7610e3..50ca44e 100644 (file)
@@ -1,3 +1,22 @@
+2019-03-11  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        [macOS] Dispatching reentrant "contextmenu" events may cause crashes
+        https://bugs.webkit.org/show_bug.cgi?id=195571
+        <rdar://problem/48086046>
+
+        Reviewed by Andy Estes.
+
+        Make ContextMenuController::handleContextMenuEvent robust against reentrancy by guarding it with a boolean flag.
+        As demonstrated in the test case, it is currently possible to force WebKit into a bad state by dispatching a
+        synthetic "contextmenu" event from within the scope of one of the "before(copy|cut|paste)" events triggered as
+        a result of handling a context menu event.
+
+        Test: fast/events/contextmenu-reentrancy-crash.html
+
+        * page/ContextMenuController.cpp:
+        (WebCore::ContextMenuController::handleContextMenuEvent):
+        * page/ContextMenuController.h:
+
 2019-03-11  Andy Estes  <aestes@apple.com>
 
         [Apple Pay] Use PKPaymentAuthorizationController to present the Apple Pay UI remotely from the Networking service on iOS
index c2cf0c2..bd7a3db 100644 (file)
@@ -68,6 +68,7 @@
 #include "UserTypingGestureIndicator.h"
 #include "WindowFeatures.h"
 #include "markup.h"
+#include <wtf/SetForScope.h>
 #include <wtf/WallTime.h>
 #include <wtf/unicode/CharacterNames.h>
 
@@ -97,6 +98,11 @@ void ContextMenuController::clearContextMenu()
 
 void ContextMenuController::handleContextMenuEvent(Event& event)
 {
+    if (m_isHandlingContextMenuEvent)
+        return;
+
+    SetForScope<bool> isHandlingContextMenuEventForScope(m_isHandlingContextMenuEvent, true);
+
     m_contextMenu = maybeCreateContextMenu(event);
     if (!m_contextMenu)
         return;
index f639648..898d0be 100644 (file)
@@ -93,6 +93,7 @@ private:
     std::unique_ptr<ContextMenu> m_contextMenu;
     RefPtr<ContextMenuProvider> m_menuProvider;
     ContextMenuContext m_context;
+    bool m_isHandlingContextMenuEvent { false };
 };
 
 } // namespace WebCore