SIGILL @ WebCore::Shape::createRasterShape -- DOS ASAN
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 8 May 2020 01:54:31 +0000 (01:54 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 8 May 2020 01:54:31 +0000 (01:54 +0000)
https://bugs.webkit.org/show_bug.cgi?id=211539

Patch by Pinki Gyanchandani <pgyanchandani@apple.com> on 2020-05-07
Reviewed by Geoffrey Garen.

Source/WebCore:

Removed the RELEASE_ASSERT because its possible for imageData to be null when imageRect size is huge value.

Test: fast/shapes/shape-outside-floats/shape-outside-imagedata-overflow.html

* rendering/shapes/Shape.cpp:
(WebCore::Shape::createRasterShape):

LayoutTests:

Added a regression test and enabled it only for WK1.

* TestExpectations:
* fast/shapes/shape-outside-floats/shape-outside-imagedata-overflow-expected.txt: Added.
* fast/shapes/shape-outside-floats/shape-outside-imagedata-overflow.html: Added.
* platform/ios-wk1/TestExpectations:
* platform/mac-wk1/TestExpectations:

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

LayoutTests/ChangeLog
LayoutTests/TestExpectations
LayoutTests/fast/shapes/shape-outside-floats/shape-outside-imagedata-overflow-expected.txt [new file with mode: 0644]
LayoutTests/fast/shapes/shape-outside-floats/shape-outside-imagedata-overflow.html [new file with mode: 0644]
LayoutTests/platform/ios-wk1/TestExpectations
LayoutTests/platform/mac-wk1/TestExpectations
Source/WebCore/ChangeLog
Source/WebCore/rendering/shapes/Shape.cpp

index 2275f61..8ab7a63 100644 (file)
@@ -1,3 +1,18 @@
+2020-05-07  Pinki Gyanchandani  <pgyanchandani@apple.com>
+
+        SIGILL @ WebCore::Shape::createRasterShape -- DOS ASAN
+        https://bugs.webkit.org/show_bug.cgi?id=211539
+
+        Reviewed by Geoffrey Garen.
+
+        Added a regression test and enabled it only for WK1.
+
+        * TestExpectations:
+        * fast/shapes/shape-outside-floats/shape-outside-imagedata-overflow-expected.txt: Added.
+        * fast/shapes/shape-outside-floats/shape-outside-imagedata-overflow.html: Added.
+        * platform/ios-wk1/TestExpectations:
+        * platform/mac-wk1/TestExpectations:
+
 2020-05-07  Devin Rousso  <drousso@apple.com>
 
         Web Inspector: Uncaught Exception: TypeError: null is not an object (evaluating 'mimeType.endsWith')
index dbf23df..470e610 100644 (file)
@@ -145,6 +145,9 @@ fast/shadow-dom/dragging-element-with-shadow-tree.html [ Skip ]
 fast/shadow-dom/dragging-element-inside-shadow-tree.html [ Skip ]
 http/tests/security/clipboard/drag-drop-html-cross-origin-iframe-in-same-origin.html [ Skip ]
 
+# rdar://problem/61793884 : making this test WK1 specific as, for WK2 its timing out.
+fast/shapes/shape-outside-floats/shape-outside-imagedata-overflow.html [ Skip ]
+
 # Only iOS supports QuickLook
 quicklook [ Skip ]
 http/tests/quicklook [ Skip ]
diff --git a/LayoutTests/fast/shapes/shape-outside-floats/shape-outside-imagedata-overflow-expected.txt b/LayoutTests/fast/shapes/shape-outside-floats/shape-outside-imagedata-overflow-expected.txt
new file mode 100644 (file)
index 0000000..f53b074
--- /dev/null
@@ -0,0 +1,2 @@
+This test passes if there is no crash.
+AA\.AA;
diff --git a/LayoutTests/fast/shapes/shape-outside-floats/shape-outside-imagedata-overflow.html b/LayoutTests/fast/shapes/shape-outside-floats/shape-outside-imagedata-overflow.html
new file mode 100644 (file)
index 0000000..70782f8
--- /dev/null
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+
+<style>
+body { shape-outside: linear-gradient(to left, red 37%, transparent 37%); float: left; }
+body,div { columns:74; }
+</style>
+
+<script>
+    if (window.testRunner)
+        testRunner.dumpAsText()
+</script>
+
+<body>This test passes if there is no crash.
+<content></content>
+<div>
+<div>AA\.AA;</div>
+</body>
+</html>
index 65226e7..82c1e3b 100644 (file)
@@ -1390,6 +1390,9 @@ fast/css/ancestor-of-hovered-element-removed.html [ Pass ]
 fast/images/animated-gif-no-layout.html [ Pass ]
 fast/scrolling/rtl-scrollbars-alternate-body-dir-attr-does-not-update-scrollbar-placement-2.html [ Pass ]
 
+# rdar://problem/61793884 : Enabling this test for WK1 only.
+fast/shapes/shape-outside-floats/shape-outside-imagedata-overflow.html [ Pass ]
+
 # w3c tests that fail
 imported/w3c/web-platform-tests/html/browsers/browsing-the-web/scroll-to-fragid/scroll-to-anchor-name.html [ Failure ]
 imported/w3c/web-platform-tests/html/browsers/browsing-the-web/scroll-to-fragid/scroll-to-id-top.html [ Failure ]
index 89032ed..702fe54 100644 (file)
@@ -30,6 +30,9 @@ http/tests/security/clipboard/drag-drop-html-cross-origin-iframe-in-same-origin.
 
 http/tests/security/xss-DENIED-xsl-external-entity-no-logging.xml [ Pass ]
 
+# rdar://problem/61793884 : Enabling this test for WK1 only.
+fast/shapes/shape-outside-floats/shape-outside-imagedata-overflow.html [ Pass ]
+
 #//////////////////////////////////////////////////////////////////////////////////////////
 # End platform-specific directories.
 #//////////////////////////////////////////////////////////////////////////////////////////
index d85b9d3..4b51fc7 100644 (file)
@@ -1,3 +1,17 @@
+2020-05-07  Pinki Gyanchandani  <pgyanchandani@apple.com>
+
+        SIGILL @ WebCore::Shape::createRasterShape -- DOS ASAN
+        https://bugs.webkit.org/show_bug.cgi?id=211539
+
+        Reviewed by Geoffrey Garen.
+
+        Removed the RELEASE_ASSERT because its possible for imageData to be null when imageRect size is huge value. 
+
+        Test: fast/shapes/shape-outside-floats/shape-outside-imagedata-overflow.html
+
+        * rendering/shapes/Shape.cpp:
+        (WebCore::Shape::createRasterShape):
+
 2020-05-07  Youenn Fablet  <youenn@apple.com>
 
         Remove AudioMediaStreamTrackRenderer::muted
index fbf1026..e36e2b8 100644 (file)
@@ -183,46 +183,57 @@ std::unique_ptr<Shape> Shape::createRasterShape(Image* image, float threshold, c
     // FIXME (149420): This buffer should not be unconditionally unaccelerated.
     std::unique_ptr<ImageBuffer> imageBuffer = ImageBuffer::create(imageRect.size(), RenderingMode::Unaccelerated);
 
-    if (imageBuffer) {
-        GraphicsContext& graphicsContext = imageBuffer->context();
-        if (image)
-            graphicsContext.drawImage(*image, IntRect(IntPoint(), imageRect.size()));
-
-        auto imageData = imageBuffer->getImageData(AlphaPremultiplication::Unpremultiplied, { IntPoint(), imageRect.size() });
-        RELEASE_ASSERT(imageData && imageData->data());
-        auto* pixelArray = imageData->data();
-        unsigned pixelArrayLength = pixelArray->length();
-        unsigned pixelArrayOffset = 3; // Each pixel is four bytes: RGBA.
-        uint8_t alphaPixelThreshold = static_cast<uint8_t>(lroundf(clampTo<float>(threshold, 0, 1) * 255.0f));
-
-        int minBufferY = std::max(0, marginRect.y() - imageRect.y());
-        int maxBufferY = std::min(imageRect.height(), marginRect.maxY() - imageRect.y());
-
-        if ((imageRect.area() * 4).unsafeGet() == pixelArrayLength) {
-            for (int y = minBufferY; y < maxBufferY; ++y) {
-                int startX = -1;
-                for (int x = 0; x < imageRect.width(); ++x, pixelArrayOffset += 4) {
-                    uint8_t alpha = pixelArray->item(pixelArrayOffset);
-                    bool alphaAboveThreshold = alpha > alphaPixelThreshold;
-                    if (startX == -1 && alphaAboveThreshold) {
-                        startX = x;
-                    } else if (startX != -1 && (!alphaAboveThreshold || x == imageRect.width() - 1)) {
-                        // We're creating "end-point exclusive" intervals here. The value of an interval's x1 is
-                        // the first index of an above-threshold pixel for y, and the value of x2 is 1+ the index
-                        // of the last above-threshold pixel.
-                        int endX = alphaAboveThreshold ? x + 1 : x;
-                        intervals->intervalAt(y + imageRect.y()).unite(IntShapeInterval(startX + imageRect.x(), endX + imageRect.x()));
-                        startX = -1;
-                    }
+    auto createShape = [&]() {
+        auto rasterShape = makeUnique<RasterShape>(WTFMove(intervals), marginRect.size());
+        rasterShape->m_writingMode = writingMode;
+        rasterShape->m_margin = margin;
+        return rasterShape;
+    };
+
+    if (!imageBuffer)
+        return createShape();
+
+    GraphicsContext& graphicsContext = imageBuffer->context();
+    if (image)
+        graphicsContext.drawImage(*image, IntRect(IntPoint(), imageRect.size()));
+
+    auto imageData = imageBuffer->getImageData(AlphaPremultiplication::Unpremultiplied, { IntPoint(), imageRect.size() });
+    
+    // Removing the Release Assert, as we could get to a value where imageData could be nullptr. A case where
+    // ImageRect.size() is huge, imageData::create can return a nullptr because data size has overflowed.
+    // Refer rdar://problem/61793884
+    if (!imageData || !imageData->data())
+        return createShape();
+
+    auto* pixelArray = imageData->data();
+    unsigned pixelArrayLength = pixelArray->length();
+    unsigned pixelArrayOffset = 3; // Each pixel is four bytes: RGBA.
+    uint8_t alphaPixelThreshold = static_cast<uint8_t>(lroundf(clampTo<float>(threshold, 0, 1) * 255.0f));
+
+    int minBufferY = std::max(0, marginRect.y() - imageRect.y());
+    int maxBufferY = std::min(imageRect.height(), marginRect.maxY() - imageRect.y());
+
+    if ((imageRect.area() * 4).unsafeGet() == pixelArrayLength) {
+        for (int y = minBufferY; y < maxBufferY; ++y) {
+            int startX = -1;
+            for (int x = 0; x < imageRect.width(); ++x, pixelArrayOffset += 4) {
+                uint8_t alpha = pixelArray->item(pixelArrayOffset);
+                bool alphaAboveThreshold = alpha > alphaPixelThreshold;
+                if (startX == -1 && alphaAboveThreshold) {
+                    startX = x;
+                } else if (startX != -1 && (!alphaAboveThreshold || x == imageRect.width() - 1)) {
+                    // We're creating "end-point exclusive" intervals here. The value of an interval's x1 is
+                    // the first index of an above-threshold pixel for y, and the value of x2 is 1+ the index
+                    // of the last above-threshold pixel.
+                    int endX = alphaAboveThreshold ? x + 1 : x;
+                    intervals->intervalAt(y + imageRect.y()).unite(IntShapeInterval(startX + imageRect.x(), endX + imageRect.x()));
+                    startX = -1;
                 }
             }
         }
     }
 
-    auto rasterShape = makeUnique<RasterShape>(WTFMove(intervals), marginRect.size());
-    rasterShape->m_writingMode = writingMode;
-    rasterShape->m_margin = margin;
-    return rasterShape;
+    return createShape();
 }
 
 std::unique_ptr<Shape> Shape::createBoxShape(const RoundedRect& roundedRect, WritingMode writingMode, float margin)