Source/WebCore: Crash in RenderBox::paintMaskImages due to a mask without an associat...
authorjchaffraix@webkit.org <jchaffraix@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 15 Sep 2011 21:59:10 +0000 (21:59 +0000)
committerjchaffraix@webkit.org <jchaffraix@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 15 Sep 2011 21:59:10 +0000 (21:59 +0000)
https://bugs.webkit.org/show_bug.cgi?id=50151

Reviewed by Simon Fraser.

Test: fast/css/empty-webkit-mask-crash.html

The crash stems from the fact that FillLayer::hasImage would walk over the linked list
of FillLayers and return true if one had an image. This means that hasImage() is true
does not mean that image() is non-NULL on all FillLayers.

* rendering/RenderBox.cpp:
(WebCore::RenderBox::paintMaskImages): Simplify the logic by doing the hasImage() check up-front
and properly check image() for each FillLayers. This has the nice benefit of changing the complexity
from O(n^2) to O(n), which was what the code expected anyway.

LayoutTests: Test for: Crash in RenderBox::paintMaskImages due to a mask without an associated image
https://bugs.webkit.org/show_bug.cgi?id=50151

Reviewed by Simon Fraser.

* fast/css/empty-webkit-mask-crash-expected.png: Added.
* fast/css/empty-webkit-mask-crash-expected.txt: Added.
* fast/css/empty-webkit-mask-crash.html: Added.

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

LayoutTests/ChangeLog
LayoutTests/fast/css/empty-webkit-mask-crash-expected.png [new file with mode: 0644]
LayoutTests/fast/css/empty-webkit-mask-crash-expected.txt [new file with mode: 0644]
LayoutTests/fast/css/empty-webkit-mask-crash.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/rendering/RenderBox.cpp

index 4ef1348..83c2822 100644 (file)
@@ -1,3 +1,14 @@
+2011-09-15  Julien Chaffraix  <jchaffraix@webkit.org>
+
+        Test for: Crash in RenderBox::paintMaskImages due to a mask without an associated image
+        https://bugs.webkit.org/show_bug.cgi?id=50151
+
+        Reviewed by Simon Fraser.
+
+        * fast/css/empty-webkit-mask-crash-expected.png: Added.
+        * fast/css/empty-webkit-mask-crash-expected.txt: Added.
+        * fast/css/empty-webkit-mask-crash.html: Added.
+
 2011-09-15  Andy Estes  <aestes@apple.com>
 
         Having an empty listener to beforeload events changes the behavior of other scripts
diff --git a/LayoutTests/fast/css/empty-webkit-mask-crash-expected.png b/LayoutTests/fast/css/empty-webkit-mask-crash-expected.png
new file mode 100644 (file)
index 0000000..b5daa85
Binary files /dev/null and b/LayoutTests/fast/css/empty-webkit-mask-crash-expected.png differ
diff --git a/LayoutTests/fast/css/empty-webkit-mask-crash-expected.txt b/LayoutTests/fast/css/empty-webkit-mask-crash-expected.txt
new file mode 100644 (file)
index 0000000..8f7871e
--- /dev/null
@@ -0,0 +1,2 @@
+https://bugs.webkit.org/show_bug.cgi?id=50151 : Crash in RenderBox::paintMaskImages due to a mask without an associated image
+The test passes if it does not CRASH (normally the output is a white page)
diff --git a/LayoutTests/fast/css/empty-webkit-mask-crash.html b/LayoutTests/fast/css/empty-webkit-mask-crash.html
new file mode 100644 (file)
index 0000000..3d8062a
--- /dev/null
@@ -0,0 +1,12 @@
+<script>
+    // We need to dump the image to get the crash but we don't care about the layout information.
+    if (window.layoutTestController)
+        layoutTestController.dumpAsText(true);
+</script>
+<style>
+*{
+    -webkit-mask-image:none,none,url(x);
+}
+</style>
+<p style="position:absolute; top: -1000px">https://bugs.webkit.org/show_bug.cgi?id=50151 : Crash in RenderBox::paintMaskImages due to a mask without an associated image<br>
+The test passes if it does not CRASH (normally the output is a white page)</p>
index 03bc9cd..5db1380 100644 (file)
@@ -1,3 +1,21 @@
+2011-09-15  Julien Chaffraix  <jchaffraix@webkit.org>
+
+        Crash in RenderBox::paintMaskImages due to a mask without an associated image
+        https://bugs.webkit.org/show_bug.cgi?id=50151
+
+        Reviewed by Simon Fraser.
+
+        Test: fast/css/empty-webkit-mask-crash.html
+
+        The crash stems from the fact that FillLayer::hasImage would walk over the linked list
+        of FillLayers and return true if one had an image. This means that hasImage() is true
+        does not mean that image() is non-NULL on all FillLayers.
+
+        * rendering/RenderBox.cpp:
+        (WebCore::RenderBox::paintMaskImages): Simplify the logic by doing the hasImage() check up-front
+        and properly check image() for each FillLayers. This has the nice benefit of changing the complexity
+        from O(n^2) to O(n), which was what the code expected anyway.
+
 2011-09-15  Eric Seidel  <eric@webkit.org>
 
         Remove ENABLE(SVG_AS_IMAGE) since all major ports have it on by default
index 65f467c..a4bc7a5 100644 (file)
@@ -949,10 +949,11 @@ void RenderBox::paintMaskImages(const PaintInfo& paintInfo, const LayoutRect& pa
         if (!allMaskImagesLoaded)
             pushTransparencyLayer = true;
 
-        if (maskBoxImage && maskLayers->hasImage()) {
+        bool hasMaskLayerWithImage = maskLayers->hasImage();
+        if (maskBoxImage && hasMaskLayerWithImage) {
             // We have a mask-box-image and mask-image, so need to composite them together before using the result as a mask.
             pushTransparencyLayer = true;
-        } else {
+        } else if (hasMaskLayerWithImage) {
             // We have to use an extra image buffer to hold the mask. Multiple mask images need
             // to composite together using source-over so that they can then combine into a single unified mask that
             // can be composited with the content using destination-in.  SVG images need to be able to set compositing modes
@@ -961,7 +962,7 @@ void RenderBox::paintMaskImages(const PaintInfo& paintInfo, const LayoutRect& pa
             // We have to check that the mask images to be rendered contain at least one image that can be actually used in rendering
             // before pushing the transparency layer.
             for (const FillLayer* fillLayer = maskLayers->next(); fillLayer; fillLayer = fillLayer->next()) {
-                if (fillLayer->hasImage() && fillLayer->image()->canRender(style()->effectiveZoom())) {
+                if (fillLayer->image() && fillLayer->image()->canRender(style()->effectiveZoom())) {
                     pushTransparencyLayer = true;
                     // We found one image that can be used in rendering, exit the loop
                     break;