Title: [144744] trunk
Revision
144744
Author
[email protected]
Date
2013-03-05 02:27:35 -0800 (Tue, 05 Mar 2013)

Log Message

[CSS Regions] Crash when MathML used in CSS Regions
https://bugs.webkit.org/show_bug.cgi?id=110686

Reviewed by David Hyatt.

Source/WebCore:

The MathML blocks trigger a children layout when computing the preferred widths. This happens to determine the preferred
logical heights of the children. When the layout reaches the line boxes computation the preferred width of the containing block
is requested. Because it wasn't computed, the layout of the children is started again to determine the preferred logical heights.
This causes an infinite recursion and triggers a stack overflow.

The patch introduces a new RAII utility class that disables fragmentation when the constructor is called and restores it
on the destructor. This class is used when computing the preferred height for the children of a MathML block.

Test: fast/regions/mathml-crash.html

* rendering/RenderObject.cpp:
(WebCore::RenderObject::setFlowThreadStateIncludingDescendants): Do not cross RenderFlowThread boundaries when updating the flow thread
state flag. The innermost flow threads need to manage their descendants flag values.
* rendering/RenderView.cpp:
(WebCore::FragmentationDisabler::FragmentationDisabler):
(WebCore):
(WebCore::FragmentationDisabler::~FragmentationDisabler):
* rendering/RenderView.h:
(FragmentationDisabler):
(WebCore):
* rendering/mathml/RenderMathMLBlock.cpp:
(WebCore::RenderMathMLBlock::computeChildrenPreferredLogicalHeights):

LayoutTests:

Add a test to verify regions and MathML do not crash.

* fast/regions/mathml-crash-expected.txt: Added.
* fast/regions/mathml-crash.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (144743 => 144744)


--- trunk/LayoutTests/ChangeLog	2013-03-05 10:05:41 UTC (rev 144743)
+++ trunk/LayoutTests/ChangeLog	2013-03-05 10:27:35 UTC (rev 144744)
@@ -1,3 +1,15 @@
+2013-03-05  Andrei Bucur  <[email protected]>
+
+        [CSS Regions] Crash when MathML used in CSS Regions
+        https://bugs.webkit.org/show_bug.cgi?id=110686
+
+        Reviewed by David Hyatt.
+
+        Add a test to verify regions and MathML do not crash.
+
+        * fast/regions/mathml-crash-expected.txt: Added.
+        * fast/regions/mathml-crash.html: Added.
+
 2013-03-05  Sudarsana Nagineni  <[email protected]>
 
         Unreviewed, EFL gardening.

Added: trunk/LayoutTests/fast/regions/mathml-crash-expected.txt (0 => 144744)


--- trunk/LayoutTests/fast/regions/mathml-crash-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/regions/mathml-crash-expected.txt	2013-03-05 10:27:35 UTC (rev 144744)
@@ -0,0 +1,8 @@
+PASS successfullyParsed is true
+
+TEST COMPLETE
+Bug 110686: [CSS Regions] Crash when MathML used in CSS Regions
+
+This test PASSES if it does not CRASH or ASSERT.
+
+

Added: trunk/LayoutTests/fast/regions/mathml-crash.html (0 => 144744)


--- trunk/LayoutTests/fast/regions/mathml-crash.html	                        (rev 0)
+++ trunk/LayoutTests/fast/regions/mathml-crash.html	2013-03-05 10:27:35 UTC (rev 144744)
@@ -0,0 +1,45 @@
+<html>
+<head>
+    <title>Test for MathML crash</title>
+    <script src=""
+    <style>
+    #example-text {
+       -webkit-flow-into: example-text-flow;
+       padding: 0;
+       margin: 0;
+    }
+    .regions {
+       -webkit-flow-from: example-text-flow;
+       border: 1px solid black;
+       width: 200px;
+       height: 50px;
+    }
+    </style>
+</head>
+<body>
+<div>
+    <p>Bug <a href="" [CSS Regions] Crash when MathML used in CSS Regions</p>
+    <p>This test PASSES if it does not CRASH or ASSERT.</p>
+    <div id="example-text">
+        <div>
+            <math>
+                <mrow>
+                    <mn>2</mn>
+                    <mo>+</mo>
+                    <mn>4</mn>
+                </mrow>
+            </math>
+        </div>
+    </div>
+    <div class="regions"></div>
+</div>
+<script type="text/_javascript_">
+if (window.testRunner)
+    testRunner.dumpAsText();
+document.body.offsetTop;
+if (window.testRunner)
+    document.getElementById("example-text").style.display = "none";
+</script>
+<script src=""
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (144743 => 144744)


--- trunk/Source/WebCore/ChangeLog	2013-03-05 10:05:41 UTC (rev 144743)
+++ trunk/Source/WebCore/ChangeLog	2013-03-05 10:27:35 UTC (rev 144744)
@@ -1,3 +1,33 @@
+2013-03-05  Andrei Bucur  <[email protected]>
+
+        [CSS Regions] Crash when MathML used in CSS Regions
+        https://bugs.webkit.org/show_bug.cgi?id=110686
+
+        Reviewed by David Hyatt.
+
+        The MathML blocks trigger a children layout when computing the preferred widths. This happens to determine the preferred
+        logical heights of the children. When the layout reaches the line boxes computation the preferred width of the containing block
+        is requested. Because it wasn't computed, the layout of the children is started again to determine the preferred logical heights.
+        This causes an infinite recursion and triggers a stack overflow.
+
+        The patch introduces a new RAII utility class that disables fragmentation when the constructor is called and restores it
+        on the destructor. This class is used when computing the preferred height for the children of a MathML block.
+
+        Test: fast/regions/mathml-crash.html
+
+        * rendering/RenderObject.cpp:
+        (WebCore::RenderObject::setFlowThreadStateIncludingDescendants): Do not cross RenderFlowThread boundaries when updating the flow thread
+        state flag. The innermost flow threads need to manage their descendants flag values.
+        * rendering/RenderView.cpp:
+        (WebCore::FragmentationDisabler::FragmentationDisabler):
+        (WebCore):
+        (WebCore::FragmentationDisabler::~FragmentationDisabler):
+        * rendering/RenderView.h:
+        (FragmentationDisabler):
+        (WebCore):
+        * rendering/mathml/RenderMathMLBlock.cpp:
+        (WebCore::RenderMathMLBlock::computeChildrenPreferredLogicalHeights):
+
 2013-03-05  Mike West  <[email protected]>
 
         Cleanup: Move HitTestLocation and HitTestResult into separate files.

Modified: trunk/Source/WebCore/rendering/RenderObject.cpp (144743 => 144744)


--- trunk/Source/WebCore/rendering/RenderObject.cpp	2013-03-05 10:05:41 UTC (rev 144743)
+++ trunk/Source/WebCore/rendering/RenderObject.cpp	2013-03-05 10:27:35 UTC (rev 144744)
@@ -281,6 +281,9 @@
     setFlowThreadState(state);
 
     for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+        // If the child is a fragmentation context it already updated the descendants flag accordingly.
+        if (child->isRenderFlowThread())
+            continue;
         ASSERT(state != child->flowThreadState());
         child->setFlowThreadStateIncludingDescendants(state);
     }

Modified: trunk/Source/WebCore/rendering/RenderView.cpp (144743 => 144744)


--- trunk/Source/WebCore/rendering/RenderView.cpp	2013-03-05 10:05:41 UTC (rev 144743)
+++ trunk/Source/WebCore/rendering/RenderView.cpp	2013-03-05 10:27:35 UTC (rev 144744)
@@ -1147,4 +1147,42 @@
     info.addMember(m_legacyPrinting, "legacyPrinting");
 }
 
+FragmentationDisabler::FragmentationDisabler(RenderObject* root)
+{
+    RenderView* renderView = root->view();
+    ASSERT(renderView);
+
+    LayoutState* layoutState = renderView->layoutState();
+
+    m_root = root;
+    m_fragmenting = layoutState && layoutState->isPaginated();
+    m_flowThreadState = m_root->flowThreadState();
+#ifndef NDEBUG
+    m_layoutState = layoutState;
+#endif
+
+    if (layoutState)
+        layoutState->m_isPaginated = false;
+        
+    if (m_flowThreadState != RenderObject::NotInsideFlowThread)
+        m_root->setFlowThreadStateIncludingDescendants(RenderObject::NotInsideFlowThread);
+}
+
+FragmentationDisabler::~FragmentationDisabler()
+{
+    RenderView* renderView = m_root->view();
+    ASSERT(renderView);
+
+    LayoutState* layoutState = renderView->layoutState();
+#ifndef NDEBUG
+    ASSERT(m_layoutState == layoutState);
+#endif
+
+    if (layoutState)
+        layoutState->m_isPaginated = m_fragmenting;
+        
+    if (m_flowThreadState != RenderObject::NotInsideFlowThread)
+        m_root->setFlowThreadStateIncludingDescendants(m_flowThreadState);
+}
+
 } // namespace WebCore

Modified: trunk/Source/WebCore/rendering/RenderView.h (144743 => 144744)


--- trunk/Source/WebCore/rendering/RenderView.h	2013-03-05 10:05:41 UTC (rev 144743)
+++ trunk/Source/WebCore/rendering/RenderView.h	2013-03-05 10:27:35 UTC (rev 144744)
@@ -446,6 +446,20 @@
     RenderView* m_view;
 };
 
+class FragmentationDisabler {
+    WTF_MAKE_NONCOPYABLE(FragmentationDisabler);
+public:
+    FragmentationDisabler(RenderObject* root);
+    ~FragmentationDisabler();
+private:
+    RenderObject* m_root;
+    RenderObject::FlowThreadState m_flowThreadState;
+    bool m_fragmenting;
+#ifndef NDEBUG
+    LayoutState* m_layoutState;
+#endif
+};
+
 } // namespace WebCore
 
 #endif // RenderView_h

Modified: trunk/Source/WebCore/rendering/mathml/RenderMathMLBlock.cpp (144743 => 144744)


--- trunk/Source/WebCore/rendering/mathml/RenderMathMLBlock.cpp	2013-03-05 10:05:41 UTC (rev 144743)
+++ trunk/Source/WebCore/rendering/mathml/RenderMathMLBlock.cpp	2013-03-05 10:27:35 UTC (rev 144744)
@@ -76,10 +76,13 @@
 void RenderMathMLBlock::computeChildrenPreferredLogicalHeights()
 {
     ASSERT(needsLayout());
-    
+
+    // This is ugly, but disable fragmentation when computing the preferred heights.
+    FragmentationDisabler fragmentationDisabler(this);
+
     // Ensure a full repaint will happen after layout finishes.
     setNeedsLayout(true, MarkOnlyThis);
-    
+
     RenderView* renderView = view();
     bool hadLayoutState = renderView->layoutState();
     if (!hadLayoutState)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to