Page crashes under CGPathAddUnevenCornersRoundedRect
https://bugs.webkit.org/show_bug.cgi?id=201117

Reviewed by Dean Jackson.
Source/WebCore:

Fix crash on https://onehtmlpagechallenge.com/entries/pure-css-still-life-water-lemon.html
We were passing CG radius values where the sum of two radii was greater than the height or
width, caused by rounding when converting from floats to doubles.

Test: fast/borders/renderable-uneven-rounded-rects.html

* platform/graphics/cg/PathCG.cpp:
(WebCore::Path::platformAddPathForRoundedRect):

LayoutTests:

* fast/borders/renderable-uneven-rounded-rects-expected.txt: Added.
* fast/borders/renderable-uneven-rounded-rects.html: Added.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@249090 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index a2ca6ff..9f22b5c 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,13 @@
+2019-08-24  Simon Fraser  <simon.fraser@apple.com>
+
+        Page crashes under CGPathAddUnevenCornersRoundedRect
+        https://bugs.webkit.org/show_bug.cgi?id=201117
+
+        Reviewed by Dean Jackson.
+
+        * fast/borders/renderable-uneven-rounded-rects-expected.txt: Added.
+        * fast/borders/renderable-uneven-rounded-rects.html: Added.
+
 2019-08-24  Devin Rousso  <drousso@apple.com>
 
         Web Inspector: "Copy Rule" menu item does not propagate comments properly
diff --git a/LayoutTests/fast/borders/renderable-uneven-rounded-rects-expected.txt b/LayoutTests/fast/borders/renderable-uneven-rounded-rects-expected.txt
new file mode 100644
index 0000000..d31f6ea
--- /dev/null
+++ b/LayoutTests/fast/borders/renderable-uneven-rounded-rects-expected.txt
@@ -0,0 +1,3 @@
+This test should not crash.
+
+
diff --git a/LayoutTests/fast/borders/renderable-uneven-rounded-rects.html b/LayoutTests/fast/borders/renderable-uneven-rounded-rects.html
new file mode 100644
index 0000000..f0f24f7
--- /dev/null
+++ b/LayoutTests/fast/borders/renderable-uneven-rounded-rects.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>

+<html>

+<head>

+    <style>

+        body {

+            font-size: 7.96px;

+        }

+        .box {

+            height: 10em;

+            width: 2em;

+            border-radius: 50%;

+            border-left: .35em solid green;

+        }

+

+        .box2 {

+            height: 2em;

+            width: 10em;

+            border-radius: 50%;

+            border-top: .35em solid green;

+        }

+    </style>

+    <script>

+        if (window.testRunner)

+            testRunner.dumpAsText();

+    </script>

+</head>

+<body>

+    <p>This test should not crash.</p>

+    <div class="box"></div>

+    <div class="box2"></div>

+</body>

+</html>
\ No newline at end of file
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 7b34011..654b96e 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,19 @@
+2019-08-24  Simon Fraser  <simon.fraser@apple.com>
+
+        Page crashes under CGPathAddUnevenCornersRoundedRect
+        https://bugs.webkit.org/show_bug.cgi?id=201117
+
+        Reviewed by Dean Jackson.
+        
+        Fix crash on https://onehtmlpagechallenge.com/entries/pure-css-still-life-water-lemon.html
+        We were passing CG radius values where the sum of two radii was greater than the height or
+        width, caused by rounding when converting from floats to doubles.
+
+        Test: fast/borders/renderable-uneven-rounded-rects.html
+
+        * platform/graphics/cg/PathCG.cpp:
+        (WebCore::Path::platformAddPathForRoundedRect):
+
 2019-08-23  Simon Fraser  <simon.fraser@apple.com>
 
         RenderLayer::updateLayerPositions() doesn't propagate the ancestor flags correctly
diff --git a/Source/WebCore/platform/graphics/cg/PathCG.cpp b/Source/WebCore/platform/graphics/cg/PathCG.cpp
index 77aa9eb..32fcd74 100644
--- a/Source/WebCore/platform/graphics/cg/PathCG.cpp
+++ b/Source/WebCore/platform/graphics/cg/PathCG.cpp
@@ -307,9 +307,9 @@
         CGRect rectToDraw = rect;
         CGFloat rectWidth = CGRectGetWidth(rectToDraw);
         CGFloat rectHeight = CGRectGetHeight(rectToDraw);
-        if (rectWidth < 2 * radiusWidth)
+        if (2 * radiusWidth > rectWidth)
             radiusWidth = rectWidth / 2 - std::numeric_limits<CGFloat>::epsilon();
-        if (rectHeight < 2 * radiusHeight)
+        if (2 * radiusHeight > rectHeight)
             radiusHeight = rectHeight / 2 - std::numeric_limits<CGFloat>::epsilon();
         CGPathAddRoundedRect(ensurePlatformPath(), nullptr, rectToDraw, radiusWidth, radiusHeight);
         return;
@@ -317,7 +317,24 @@
 
 #if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101400) || (PLATFORM(IOS_FAMILY) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 120000)
     CGRect rectToDraw = rect;
+    
+    enum Corners {
+        BottomLeft,
+        BottomRight,
+        TopRight,
+        TopLeft
+    };
     CGSize corners[4] = { bottomLeftRadius, bottomRightRadius, topRightRadius, topLeftRadius };
+
+    CGFloat rectWidth = CGRectGetWidth(rectToDraw);
+    CGFloat rectHeight = CGRectGetHeight(rectToDraw);
+    
+    // Clamp the radii after conversion to CGFloats.
+    corners[TopRight].width = std::min(corners[TopRight].width, rectWidth - corners[TopLeft].width);
+    corners[BottomRight].width = std::min(corners[BottomRight].width, rectWidth - corners[BottomLeft].width);
+    corners[BottomLeft].height = std::min(corners[BottomLeft].height, rectHeight - corners[TopLeft].height);
+    corners[BottomRight].height = std::min(corners[BottomRight].height, rectHeight - corners[TopRight].height);
+
     CGPathAddUnevenCornersRoundedRect(ensurePlatformPath(), nullptr, rectToDraw, corners);
     return;
 #endif