Title: [226492] trunk
Revision
226492
Author
[email protected]
Date
2018-01-06 22:31:14 -0800 (Sat, 06 Jan 2018)

Log Message

Possible crash computing event regions
https://bugs.webkit.org/show_bug.cgi?id=181368
rdar://problem/34847081

Reviewed by Zalan Bujtas.

Source/WebCore:

Don't trigger layout in Element::absoluteEventHandlerBounds(), since this can run arbirary script
which might delete elements or re-enter Document::absoluteRegionForEventTargets().

It's OK to not trigger layout, because if layout is dirty, the next layout will update event regions again.

Add a LayoutDisallowedScope to check that Document::absoluteRegionForEventTargets() doesn't
trigger layout, and move the check for LayoutDisallowedScope::isLayoutAllowed() from Document::updateLayout()
to LayoutContext::layout(), since some layouts don't happen via the former (e.g. the one being removed here).

The test checks that the assertion does not fire. I was not able to get a reliable test for any crash.

Test: fast/events/event-handler-regions-layout.html

* dom/Document.cpp:
(WebCore::Document::updateLayout):
(WebCore::Document::absoluteRegionForEventTargets):
* dom/Element.cpp:
(WebCore::Element::absoluteEventHandlerBounds):
* page/LayoutContext.cpp:
(WebCore::LayoutContext::layout):
* rendering/LayoutDisallowedScope.h: Move the #ifdefs around to avoid defining the enum twice.
(WebCore::LayoutDisallowedScope::LayoutDisallowedScope):
(WebCore::LayoutDisallowedScope::isLayoutAllowed):

LayoutTests:

* fast/events/event-handler-regions-layout-expected.txt: Added.
* fast/events/event-handler-regions-layout.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (226491 => 226492)


--- trunk/LayoutTests/ChangeLog	2018-01-07 05:48:47 UTC (rev 226491)
+++ trunk/LayoutTests/ChangeLog	2018-01-07 06:31:14 UTC (rev 226492)
@@ -1,5 +1,16 @@
 2018-01-06  Simon Fraser  <[email protected]>
 
+        Possible crash computing event regions
+        https://bugs.webkit.org/show_bug.cgi?id=181368
+        rdar://problem/34847081
+
+        Reviewed by Zalan Bujtas.
+
+        * fast/events/event-handler-regions-layout-expected.txt: Added.
+        * fast/events/event-handler-regions-layout.html: Added.
+
+2018-01-06  Simon Fraser  <[email protected]>
+
         Crash under RenderLayer::scrollTo() with marquee
         https://bugs.webkit.org/show_bug.cgi?id=181349
         rdar://problem/36190168

Added: trunk/LayoutTests/fast/events/event-handler-regions-layout-expected.txt (0 => 226492)


--- trunk/LayoutTests/fast/events/event-handler-regions-layout-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/events/event-handler-regions-layout-expected.txt	2018-01-07 06:31:14 UTC (rev 226492)
@@ -0,0 +1,3 @@
+This test should not assert in debug builds.
+
+  

Added: trunk/LayoutTests/fast/events/event-handler-regions-layout.html (0 => 226492)


--- trunk/LayoutTests/fast/events/event-handler-regions-layout.html	                        (rev 0)
+++ trunk/LayoutTests/fast/events/event-handler-regions-layout.html	2018-01-07 06:31:14 UTC (rev 226492)
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script>
+    if (window.testRunner) {
+        testRunner.dumpAsText();
+        testRunner.waitUntilDone();
+    }
+
+    function doTest()
+    {
+        var iframe = document.getElementById('iframe');
+        var frameDocElement = iframe.contentDocument.documentElement;
+        frameDocElement.innerHTML = '<object></object>';
+        frameDocElement.addEventListener('beforeload', frameBeforeLoad, true);
+        frameDocElement.offsetWidth;
+    }
+    
+    function frameBeforeLoad()
+    {
+        var wrapper = document.getElementById('wrapper');
+        document.getElementById('destination_frame').contentDocument.body.appendChild(wrapper);
+
+        if (window.testRunner)
+            testRunner.notifyDone();
+    }
+
+    window.addEventListener('load', doTest, false);
+    </script>
+</head>
+<body>
+    <p>This test should not assert in debug builds.</p>
+    <iframe id='iframe'></iframe>
+    <iframe id='destination_frame' srcdoc="<body>Test</body>"></iframe>
+    <div id="wrapper">
+        <div id="wheelie">wheel handler</div>
+    </div>
+</div>
+<script>
+    document.getElementById('wheelie').addEventListener('mousewheel', function(e) { });
+</script>
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (226491 => 226492)


--- trunk/Source/WebCore/ChangeLog	2018-01-07 05:48:47 UTC (rev 226491)
+++ trunk/Source/WebCore/ChangeLog	2018-01-07 06:31:14 UTC (rev 226492)
@@ -1,5 +1,37 @@
 2018-01-06  Simon Fraser  <[email protected]>
 
+        Possible crash computing event regions
+        https://bugs.webkit.org/show_bug.cgi?id=181368
+        rdar://problem/34847081
+
+        Reviewed by Zalan Bujtas.
+
+        Don't trigger layout in Element::absoluteEventHandlerBounds(), since this can run arbirary script
+        which might delete elements or re-enter Document::absoluteRegionForEventTargets().
+
+        It's OK to not trigger layout, because if layout is dirty, the next layout will update event regions again.
+
+        Add a LayoutDisallowedScope to check that Document::absoluteRegionForEventTargets() doesn't
+        trigger layout, and move the check for LayoutDisallowedScope::isLayoutAllowed() from Document::updateLayout()
+        to LayoutContext::layout(), since some layouts don't happen via the former (e.g. the one being removed here).
+
+        The test checks that the assertion does not fire. I was not able to get a reliable test for any crash.
+
+        Test: fast/events/event-handler-regions-layout.html
+
+        * dom/Document.cpp:
+        (WebCore::Document::updateLayout):
+        (WebCore::Document::absoluteRegionForEventTargets):
+        * dom/Element.cpp:
+        (WebCore::Element::absoluteEventHandlerBounds):
+        * page/LayoutContext.cpp:
+        (WebCore::LayoutContext::layout):
+        * rendering/LayoutDisallowedScope.h: Move the #ifdefs around to avoid defining the enum twice.
+        (WebCore::LayoutDisallowedScope::LayoutDisallowedScope):
+        (WebCore::LayoutDisallowedScope::isLayoutAllowed):
+
+2018-01-06  Simon Fraser  <[email protected]>
+
         Crash under RenderLayer::scrollTo() with marquee
         https://bugs.webkit.org/show_bug.cgi?id=181349
         rdar://problem/36190168

Modified: trunk/Source/WebCore/dom/Document.cpp (226491 => 226492)


--- trunk/Source/WebCore/dom/Document.cpp	2018-01-07 05:48:47 UTC (rev 226491)
+++ trunk/Source/WebCore/dom/Document.cpp	2018-01-07 06:31:14 UTC (rev 226492)
@@ -1969,7 +1969,6 @@
 void Document::updateLayout()
 {
     ASSERT(isMainThread());
-    ASSERT(LayoutDisallowedScope::isLayoutAllowed());
 
     RefPtr<FrameView> frameView = view();
     if (frameView && frameView->layoutContext().isInRenderTreeLayout()) {
@@ -6645,6 +6644,8 @@
 
 Document::RegionFixedPair Document::absoluteRegionForEventTargets(const EventTargetSet* targets)
 {
+    LayoutDisallowedScope layoutDisallowedScope(LayoutDisallowedScope::Reason::ReentrancyAvoidance);
+
     if (!targets)
         return RegionFixedPair(Region(), false);
 

Modified: trunk/Source/WebCore/dom/Element.cpp (226491 => 226492)


--- trunk/Source/WebCore/dom/Element.cpp	2018-01-07 05:48:47 UTC (rev 226491)
+++ trunk/Source/WebCore/dom/Element.cpp	2018-01-07 06:31:14 UTC (rev 226492)
@@ -1141,9 +1141,6 @@
     if (!frameView)
         return LayoutRect();
 
-    if (frameView->needsLayout())
-        frameView->layoutContext().layout();
-
     return absoluteEventBoundsOfElementAndDescendants(includesFixedPositionElements);
 }
 

Modified: trunk/Source/WebCore/page/LayoutContext.cpp (226491 => 226492)


--- trunk/Source/WebCore/page/LayoutContext.cpp	2018-01-07 05:48:47 UTC (rev 226491)
+++ trunk/Source/WebCore/page/LayoutContext.cpp	2018-01-07 06:31:14 UTC (rev 226492)
@@ -31,6 +31,7 @@
 #include "Document.h"
 #include "FrameView.h"
 #include "InspectorInstrumentation.h"
+#include "LayoutDisallowedScope.h"
 #include "LayoutState.h"
 #include "Logging.h"
 #include "RenderElement.h"
@@ -122,6 +123,7 @@
     LOG_WITH_STREAM(Layout, stream << "FrameView " << &view() << " LayoutContext::layout() with size " << view().layoutSize());
 
     RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(!frame().document()->inRenderTreeUpdate());
+    ASSERT(LayoutDisallowedScope::isLayoutAllowed());
     ASSERT(!view().isPainting());
     ASSERT(frame().view() == &view());
     ASSERT(frame().document());

Modified: trunk/Source/WebCore/rendering/LayoutDisallowedScope.h (226491 => 226492)


--- trunk/Source/WebCore/rendering/LayoutDisallowedScope.h	2018-01-07 05:48:47 UTC (rev 226491)
+++ trunk/Source/WebCore/rendering/LayoutDisallowedScope.h	2018-01-07 06:31:14 UTC (rev 226492)
@@ -27,11 +27,14 @@
 
 namespace WebCore {
 
-#if !ASSERT_DISABLED
-
 class LayoutDisallowedScope {
 public:
-    enum class Reason { PerformanceOptimization };
+    enum class Reason { PerformanceOptimization, ReentrancyAvoidance };
+
+#if ASSERT_DISABLED
+    LayoutDisallowedScope(Reason) { }
+    static bool isLayoutAllowed() { return true; }
+#else
     LayoutDisallowedScope(Reason)
         : m_previousAssertion(s_currentAssertion)
     {
@@ -48,17 +51,7 @@
 private:
     LayoutDisallowedScope* m_previousAssertion;
     static LayoutDisallowedScope* s_currentAssertion;
+#endif
 };
 
-#else
-
-class LayoutDisallowedScope {
-public:
-    enum class Reason { PerformanceOptimization };
-    LayoutDisallowedScope(Reason) { }
-    static bool isLayoutAllowed() { return true; }
-};
-
-#endif
-
 }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to