Title: [105120] trunk
Revision
105120
Author
[email protected]
Date
2012-01-16 18:25:52 -0800 (Mon, 16 Jan 2012)

Log Message

Heap-use-after-free in WebCore::RenderBlock::selectionGaps
https://bugs.webkit.org/show_bug.cgi?id=75013

Reviewed by David Hyatt.

Source/WebCore:

Test: fast/table/multiple-captions-crash3.html
      fast/table/multiple-captions-crash4.html
      fast/table/multiple-captions-crash5.html

When a child float is removed, the parent needs to ensure any reference to the
child is also removed from the floating objects list in any sibling block that
it intruded into.

* rendering/RenderBlock.cpp:
(WebCore::RenderBlock::markSiblingsWithFloatsForLayout):
* rendering/RenderBox.cpp:
(WebCore::RenderBox::removeFloatingOrPositionedChildFromBlockLists):

LayoutTests:

In multiple-captions-crash3.html a floating object is added as a child to a caption element, then removed and
added as a child to another caption element. When added to the first caption element it is added
to the floating objects list of both the parent tbody element and the keygen element, as it intrudes
into the latter. When removed, a stale reference to the floating object remains in the keygen element.
When the keygen element is in layout it attempts to access the stale reference to the floating object and
crashes. The fix is to ensure that any floats added as intruding floats to sibling blocks are removed
when the child is removed from the tree.

multiple-captions-crash4.html and multiple-captions-crash5.html are variants of this scenario.

* fast/table/multiple-captions-crash3-expected.html: Added.
* fast/table/multiple-captions-crash3.html: Added.
* fast/table/multiple-captions-crash4-expected.html: Added.
* fast/table/multiple-captions-crash4.html: Added.
* fast/table/multiple-captions-crash5-expected.html: Added.
* fast/table/multiple-captions-crash5.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (105119 => 105120)


--- trunk/LayoutTests/ChangeLog	2012-01-17 02:00:48 UTC (rev 105119)
+++ trunk/LayoutTests/ChangeLog	2012-01-17 02:25:52 UTC (rev 105120)
@@ -1,3 +1,27 @@
+2012-01-16  Robert Hogan  <[email protected]>
+
+        Heap-use-after-free in WebCore::RenderBlock::selectionGaps
+        https://bugs.webkit.org/show_bug.cgi?id=75013
+
+        Reviewed by David Hyatt.
+
+        In multiple-captions-crash3.html a floating object is added as a child to a caption element, then removed and
+        added as a child to another caption element. When added to the first caption element it is added
+        to the floating objects list of both the parent tbody element and the keygen element, as it intrudes 
+        into the latter. When removed, a stale reference to the floating object remains in the keygen element. 
+        When the keygen element is in layout it attempts to access the stale reference to the floating object and 
+        crashes. The fix is to ensure that any floats added as intruding floats to sibling blocks are removed 
+        when the child is removed from the tree.
+
+        multiple-captions-crash4.html and multiple-captions-crash5.html are variants of this scenario.
+
+        * fast/table/multiple-captions-crash3-expected.html: Added.
+        * fast/table/multiple-captions-crash3.html: Added.
+        * fast/table/multiple-captions-crash4-expected.html: Added.
+        * fast/table/multiple-captions-crash4.html: Added.
+        * fast/table/multiple-captions-crash5-expected.html: Added.
+        * fast/table/multiple-captions-crash5.html: Added.
+
 2012-01-16  Filip Pizlo  <[email protected]>
 
         DFG should be able to do JS and custom getter caching

Added: trunk/LayoutTests/fast/table/multiple-captions-crash3-expected.html (0 => 105120)


--- trunk/LayoutTests/fast/table/multiple-captions-crash3-expected.html	                        (rev 0)
+++ trunk/LayoutTests/fast/table/multiple-captions-crash3-expected.html	2012-01-17 02:25:52 UTC (rev 105120)
@@ -0,0 +1,46 @@
+<html>
+<head>
+<style>
+.c2 { display: table-caption; position: relative; }
+.c9 { visibility: collapse; height: 65536px; }
+.c15 { display: inline; float: right;}
+</style>
+<script>
+if (window.layoutTestController) {
+    layoutTestController.waitUntilDone();
+}
+
+var nodes = Array();
+
+function tryToCrash()
+{
+    document.execCommand("SelectAll", false, "");
+    setTimeout('layoutTestController.notifyDone();',1000);
+}
+
+function boom() {
+    try { nodes[3] = document.createElement('tbody'); } catch(e) {}
+    try { nodes[3].setAttribute('class', 'c2'); } catch(e) {}
+    try { document.documentElement.appendChild(nodes[3]); } catch(e) {}
+    try { nodes[4] = document.createElement('col'); } catch(e) {}
+    try { nodes[4].setAttribute('class', 'c15'); } catch(e) {}
+    try { nodes[3].appendChild(nodes[4]); } catch(e) {}
+    try { nodes[6] = document.createElement('keygen'); } catch(e) {}
+    try { nodes[6].setAttribute('class', 'c2'); } catch(e) {}
+    try { document.documentElement.appendChild(nodes[6]); } catch(e) {}
+    try { nodes[8] = document.createElement('a'); } catch(e) {}
+    try { nodes[4].appendChild(nodes[8]); } catch(e) {}
+    try { nodes[21] = document.createElement('tr'); } catch(e) {}
+    try { nodes[21].setAttribute('class', 'c9'); } catch(e) {}
+    try { nodes[8].appendChild(nodes[21]); } catch(e) {}
+    try { nodes[29] = document.createElement('caption'); } catch(e) {}
+    setTimeout('try { nodes[29].appendChild(nodes[4]); } catch(e) {}', 561);
+    setTimeout('window.scrollBy(-37, 59);', 203);
+    setTimeout('tryToCrash();', 402);
+}
+</script>
+</head>
+<body _onLoad_="setTimeout('boom();',0)">
+Passes if it doesn't crash!
+</body>
+</html>
\ No newline at end of file

Added: trunk/LayoutTests/fast/table/multiple-captions-crash3.html (0 => 105120)


--- trunk/LayoutTests/fast/table/multiple-captions-crash3.html	                        (rev 0)
+++ trunk/LayoutTests/fast/table/multiple-captions-crash3.html	2012-01-17 02:25:52 UTC (rev 105120)
@@ -0,0 +1,46 @@
+<html>
+<head>
+<style>
+.c2 { display: table-caption; position: relative; }
+.c9 { visibility: collapse; height: 65536px; }
+.c15 { display: inline; float: right;}
+</style>
+<script>
+if (window.layoutTestController) {
+    layoutTestController.waitUntilDone();
+}
+
+var nodes = Array();
+
+function tryToCrash()
+{
+    document.execCommand("SelectAll", false, "");
+    setTimeout('layoutTestController.notifyDone();',1000);
+}
+
+function boom() {
+    try { nodes[3] = document.createElement('tbody'); } catch(e) {}
+    try { nodes[3].setAttribute('class', 'c2'); } catch(e) {}
+    try { document.documentElement.appendChild(nodes[3]); } catch(e) {}
+    try { nodes[4] = document.createElement('col'); } catch(e) {}
+    try { nodes[4].setAttribute('class', 'c15'); } catch(e) {}
+    try { nodes[3].appendChild(nodes[4]); } catch(e) {}
+    try { nodes[6] = document.createElement('keygen'); } catch(e) {}
+    try { nodes[6].setAttribute('class', 'c2'); } catch(e) {}
+    try { document.documentElement.appendChild(nodes[6]); } catch(e) {}
+    try { nodes[8] = document.createElement('a'); } catch(e) {}
+    try { nodes[4].appendChild(nodes[8]); } catch(e) {}
+    try { nodes[21] = document.createElement('tr'); } catch(e) {}
+    try { nodes[21].setAttribute('class', 'c9'); } catch(e) {}
+    try { nodes[8].appendChild(nodes[21]); } catch(e) {}
+    try { nodes[29] = document.createElement('caption'); } catch(e) {}
+    setTimeout('try { nodes[29].appendChild(nodes[4]); } catch(e) {}', 561);
+    setTimeout('window.scrollBy(-37, 59);', 203);
+    setTimeout('tryToCrash();', 402);
+}
+</script>
+</head>
+<body _onLoad_="setTimeout('boom();',0)">
+Passes if it doesn't crash!
+</body>
+</html>
\ No newline at end of file

Added: trunk/LayoutTests/fast/table/multiple-captions-crash4-expected.html (0 => 105120)


--- trunk/LayoutTests/fast/table/multiple-captions-crash4-expected.html	                        (rev 0)
+++ trunk/LayoutTests/fast/table/multiple-captions-crash4-expected.html	2012-01-17 02:25:52 UTC (rev 105120)
@@ -0,0 +1,49 @@
+<html>
+<head>
+<style>
+.c10 { display: table-caption; width: 65536px; }
+.c12 > .c7 { visibility: hidden; float: left; }
+.c13:nth-of-type(2n) { color: Yellow; }
+.c15:nth-last-of-type(-n+6) { display: -webkit-box; padding-left: 65536px; }
+</style>
+
+<script>
+if (window.layoutTestController) {
+    layoutTestController.waitUntilDone();
+}
+
+var nodes = Array();
+
+function tryToCrash()
+{
+    try { nodes[84].setAttribute('class', 'c18'); } catch(e) {};
+    setTimeout('layoutTestController.notifyDone();',1000);
+}
+
+function boom() {
+    try { nodes[8] = document.createElement('select'); } catch(e) {}
+    try { nodes[8].setAttribute('class', 'c7'); } catch(e) {}
+    try { nodes[16] = document.createElement('abbr'); } catch(e) {}
+    try { nodes[84] = document.createElement('li'); } catch(e) {}
+    try { document.documentElement.appendChild(nodes[84]); } catch(e) {}
+    try { nodes[91] = document.createElement('caption'); } catch(e) {}
+    try { nodes[91].setAttribute('class', 'c12'); } catch(e) {}
+    try { document.documentElement.appendChild(nodes[91]); } catch(e) {}
+    try { nodes[92] = document.createElement('details'); } catch(e) {}
+    try { nodes[92].setAttribute('class', 'c10'); } catch(e) {}
+    try { document.documentElement.appendChild(nodes[92]); } catch(e) {}
+    try { nodes[94] = document.createElement('ruby'); } catch(e) {}
+    try { nodes[94].setAttribute('class', 'c13'); } catch(e) {}
+    try { document.documentElement.appendChild(nodes[94]); } catch(e) {}
+
+    setTimeout("try { nodes[8].setAttribute('class', 'c15'); } catch(e) {}", 616);
+    setTimeout('try { nodes[91].appendChild(nodes[8]); } catch(e) {}', 502);
+    setTimeout('try { nodes[92].appendChild(nodes[16]); } catch(e) {}', 461);
+    setTimeout('tryToCrash();', 519);
+}
+</script>
+</head>
+<body _onLoad_="setTimeout('boom();',0)">
+Passes if it doesn't crash!
+</body>
+</html>
\ No newline at end of file

Added: trunk/LayoutTests/fast/table/multiple-captions-crash4.html (0 => 105120)


--- trunk/LayoutTests/fast/table/multiple-captions-crash4.html	                        (rev 0)
+++ trunk/LayoutTests/fast/table/multiple-captions-crash4.html	2012-01-17 02:25:52 UTC (rev 105120)
@@ -0,0 +1,49 @@
+<html>
+<head>
+<style>
+.c10 { display: table-caption; width: 65536px; }
+.c12 > .c7 { visibility: hidden; float: left; }
+.c13:nth-of-type(2n) { color: Yellow; }
+.c15:nth-last-of-type(-n+6) { display: -webkit-box; padding-left: 65536px; }
+</style>
+
+<script>
+if (window.layoutTestController) {
+    layoutTestController.waitUntilDone();
+}
+
+var nodes = Array();
+
+function tryToCrash()
+{
+    try { nodes[84].setAttribute('class', 'c18'); } catch(e) {};
+    setTimeout('layoutTestController.notifyDone();',1000);
+}
+
+function boom() {
+    try { nodes[8] = document.createElement('select'); } catch(e) {}
+    try { nodes[8].setAttribute('class', 'c7'); } catch(e) {}
+    try { nodes[16] = document.createElement('abbr'); } catch(e) {}
+    try { nodes[84] = document.createElement('li'); } catch(e) {}
+    try { document.documentElement.appendChild(nodes[84]); } catch(e) {}
+    try { nodes[91] = document.createElement('caption'); } catch(e) {}
+    try { nodes[91].setAttribute('class', 'c12'); } catch(e) {}
+    try { document.documentElement.appendChild(nodes[91]); } catch(e) {}
+    try { nodes[92] = document.createElement('details'); } catch(e) {}
+    try { nodes[92].setAttribute('class', 'c10'); } catch(e) {}
+    try { document.documentElement.appendChild(nodes[92]); } catch(e) {}
+    try { nodes[94] = document.createElement('ruby'); } catch(e) {}
+    try { nodes[94].setAttribute('class', 'c13'); } catch(e) {}
+    try { document.documentElement.appendChild(nodes[94]); } catch(e) {}
+
+    setTimeout("try { nodes[8].setAttribute('class', 'c15'); } catch(e) {}", 616);
+    setTimeout('try { nodes[91].appendChild(nodes[8]); } catch(e) {}', 502);
+    setTimeout('try { nodes[92].appendChild(nodes[16]); } catch(e) {}', 461);
+    setTimeout('tryToCrash();', 519);
+}
+</script>
+</head>
+<body _onLoad_="setTimeout('boom();',0)">
+Passes if it doesn't crash!
+</body>
+</html>
\ No newline at end of file

Added: trunk/LayoutTests/fast/table/multiple-captions-crash5-expected.html (0 => 105120)


--- trunk/LayoutTests/fast/table/multiple-captions-crash5-expected.html	                        (rev 0)
+++ trunk/LayoutTests/fast/table/multiple-captions-crash5-expected.html	2012-01-17 02:25:52 UTC (rev 105120)
@@ -0,0 +1,42 @@
+<html>
+<head>
+<style>
+.c0 { display: table-caption; width: 0px; }
+.c7 { float: right; padding-right: 100px; padding-bottom: 100px;}
+</style>
+<script>
+if (window.layoutTestController) {
+    layoutTestController.waitUntilDone();
+}
+
+var nodes = Array();
+
+function tryToCrash()
+{
+    try { nodes[91].appendChild(nodes[39]); } catch(e) {}
+    setTimeout('layoutTestController.notifyDone();',1000);
+}
+
+function boom() {
+    try { nodes[8] = document.createElement('dfn'); } catch(e) {}
+    try { nodes[8].setAttribute('class', 'c7'); } catch(e) {}
+    try { nodes[30] = document.createElement('span'); } catch(e) {}
+    try { nodes[39] = document.createElement('strong'); } catch(e) {}
+    try { nodes[69] = document.createElement('header'); } catch(e) {}
+    try { nodes[39].appendChild(nodes[69]); } catch(e) {}
+    try { nodes[89] = document.createElement('nav'); } catch(e) {}
+    try { nodes[89].setAttribute('class', 'c0'); } catch(e) {}
+    try { document.documentElement.appendChild(nodes[89]); } catch(e) {}
+    try { nodes[91] = document.createElement('form'); } catch(e) {}
+    try { nodes[91].setAttribute('class', 'c0'); } catch(e) {}
+    try { document.documentElement.appendChild(nodes[91]); } catch(e) {}
+    try { nodes[89].appendChild(nodes[8]); } catch(e) {}
+    setTimeout('try { nodes[30].appendChild(nodes[89]); } catch(e) {}', 4);
+    setTimeout('tryToCrash();', 0);
+}
+</script>
+</head>
+<body _onLoad_="setTimeout('boom();',0)">
+Passes if it doesn't crash!
+</body>
+</html>
\ No newline at end of file

Added: trunk/LayoutTests/fast/table/multiple-captions-crash5.html (0 => 105120)


--- trunk/LayoutTests/fast/table/multiple-captions-crash5.html	                        (rev 0)
+++ trunk/LayoutTests/fast/table/multiple-captions-crash5.html	2012-01-17 02:25:52 UTC (rev 105120)
@@ -0,0 +1,42 @@
+<html>
+<head>
+<style>
+.c0 { display: table-caption; width: 0px; }
+.c7 { float: right; padding-right: 100px; padding-bottom: 100px;}
+</style>
+<script>
+if (window.layoutTestController) {
+    layoutTestController.waitUntilDone();
+}
+
+var nodes = Array();
+
+function tryToCrash()
+{
+    try { nodes[91].appendChild(nodes[39]); } catch(e) {}
+    setTimeout('layoutTestController.notifyDone();',1000);
+}
+
+function boom() {
+    try { nodes[8] = document.createElement('dfn'); } catch(e) {}
+    try { nodes[8].setAttribute('class', 'c7'); } catch(e) {}
+    try { nodes[30] = document.createElement('span'); } catch(e) {}
+    try { nodes[39] = document.createElement('strong'); } catch(e) {}
+    try { nodes[69] = document.createElement('header'); } catch(e) {}
+    try { nodes[39].appendChild(nodes[69]); } catch(e) {}
+    try { nodes[89] = document.createElement('nav'); } catch(e) {}
+    try { nodes[89].setAttribute('class', 'c0'); } catch(e) {}
+    try { document.documentElement.appendChild(nodes[89]); } catch(e) {}
+    try { nodes[91] = document.createElement('form'); } catch(e) {}
+    try { nodes[91].setAttribute('class', 'c0'); } catch(e) {}
+    try { document.documentElement.appendChild(nodes[91]); } catch(e) {}
+    try { nodes[89].appendChild(nodes[8]); } catch(e) {}
+    setTimeout('try { nodes[30].appendChild(nodes[89]); } catch(e) {}', 4);
+    setTimeout('tryToCrash();', 0);
+}
+</script>
+</head>
+<body _onLoad_="setTimeout('boom();',0)">
+Passes if it doesn't crash!
+</body>
+</html>
\ No newline at end of file

Modified: trunk/Source/WebCore/ChangeLog (105119 => 105120)


--- trunk/Source/WebCore/ChangeLog	2012-01-17 02:00:48 UTC (rev 105119)
+++ trunk/Source/WebCore/ChangeLog	2012-01-17 02:25:52 UTC (rev 105120)
@@ -1,3 +1,23 @@
+2012-01-16  Robert Hogan  <[email protected]>
+
+        Heap-use-after-free in WebCore::RenderBlock::selectionGaps
+        https://bugs.webkit.org/show_bug.cgi?id=75013
+
+        Reviewed by David Hyatt.
+
+        Test: fast/table/multiple-captions-crash3.html
+              fast/table/multiple-captions-crash4.html
+              fast/table/multiple-captions-crash5.html
+
+        When a child float is removed, the parent needs to ensure any reference to the
+        child is also removed from the floating objects list in any sibling block that 
+        it intruded into.
+
+        * rendering/RenderBlock.cpp:
+        (WebCore::RenderBlock::markSiblingsWithFloatsForLayout):
+        * rendering/RenderBox.cpp:
+        (WebCore::RenderBox::removeFloatingOrPositionedChildFromBlockLists):
+
 2012-01-16  Enrica Casucci  <[email protected]>
 
         REGRESSION: r102553 Autocorrection bubble doesn't show up

Modified: trunk/Source/WebCore/rendering/RenderBlock.cpp (105119 => 105120)


--- trunk/Source/WebCore/rendering/RenderBlock.cpp	2012-01-17 02:00:48 UTC (rev 105119)
+++ trunk/Source/WebCore/rendering/RenderBlock.cpp	2012-01-17 02:25:52 UTC (rev 105120)
@@ -4065,13 +4065,17 @@
     }
 }
 
-void RenderBlock::markSiblingsWithFloatsForLayout()
+void RenderBlock::markSiblingsWithFloatsForLayout(RenderBox* floatToRemove)
 {
+    if (!m_floatingObjects)
+        return;
     const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
     FloatingObjectSetIterator end = floatingObjectSet.end();
     for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
         if (logicalBottomForFloat(*it) > logicalHeight()) {
             RenderBox* floatingBox = (*it)->renderer();
+            if (floatToRemove && floatingBox != floatToRemove)
+                continue;
 
             RenderObject* next = nextSibling();
             while (next) {

Modified: trunk/Source/WebCore/rendering/RenderBlock.h (105119 => 105120)


--- trunk/Source/WebCore/rendering/RenderBlock.h	2012-01-17 02:00:48 UTC (rev 105119)
+++ trunk/Source/WebCore/rendering/RenderBlock.h	2012-01-17 02:25:52 UTC (rev 105120)
@@ -118,7 +118,7 @@
     bool generatesLineBoxesForInlineChild(RenderObject*);
 
     void markAllDescendantsWithFloatsForLayout(RenderBox* floatToRemove = 0, bool inLayout = true);
-    void markSiblingsWithFloatsForLayout();
+    void markSiblingsWithFloatsForLayout(RenderBox* floatToRemove = 0);
     void markPositionedObjectsForLayout();
     virtual void markForPaginationRelayoutIfNeeded();
     

Modified: trunk/Source/WebCore/rendering/RenderBox.cpp (105119 => 105120)


--- trunk/Source/WebCore/rendering/RenderBox.cpp	2012-01-17 02:00:48 UTC (rev 105119)
+++ trunk/Source/WebCore/rendering/RenderBox.cpp	2012-01-17 02:25:52 UTC (rev 105120)
@@ -286,6 +286,7 @@
             if (parent && parent->isDeprecatedFlexibleBox())
                 parentBlock = toRenderBlock(parent);
 
+            parentBlock->markSiblingsWithFloatsForLayout(this);
             parentBlock->markAllDescendantsWithFloatsForLayout(this, false);
         }
     }
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to