merge per request

R=awhalley@google.com
TBR=reed@google.com
BUG=638223
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2284303004
NOTREECHECKS=true
NOTRY=true
NOPRESUBMIT=true

Review-Url: https://codereview.chromium.org/2284303004
diff --git a/src/core/SkGeometry.cpp b/src/core/SkGeometry.cpp
index 7dd5359..03a63b2 100644
--- a/src/core/SkGeometry.cpp
+++ b/src/core/SkGeometry.cpp
@@ -1170,10 +1170,24 @@
 
 int SkConic::chopIntoQuadsPOW2(SkPoint pts[], int pow2) const {
     SkASSERT(pow2 >= 0);
+    *pts = fPts[0];
+    SkDEBUGCODE(SkPoint* endPts);
+    if (pow2 == kMaxConicToQuadPOW2) {  // If an extreme weight generates many quads ...
+        SkConic dst[2];
+        this->chop(dst);
+        // check to see if the first chop generates a pair of lines
+        if (dst[0].fPts[1] == dst[0].fPts[2] && dst[1].fPts[0] == dst[1].fPts[1]) {
+            pts[1] = pts[2] = pts[3] = dst[0].fPts[1];  // set ctrl == end to make lines
+            pts[4] = dst[1].fPts[2];
+            pow2 = 1;
+            SkDEBUGCODE(endPts = &pts[5]);
+            goto commonFinitePtCheck;
+        }
+    }
+    SkDEBUGCODE(endPts = ) subdivide(*this, pts + 1, pow2);
+commonFinitePtCheck:
     const int quadCount = 1 << pow2;
     const int ptCount = 2 * quadCount + 1;
-    *pts = fPts[0];
-    SkDEBUGCODE(SkPoint* endPts =) subdivide(*this, pts + 1, pow2);
     SkASSERT(endPts - pts == ptCount);
     if (!SkPointsAreFinite(pts, ptCount)) {
         // if we generated a non-finite, pin ourselves to the middle of the hull,
diff --git a/src/core/SkGeometry.h b/src/core/SkGeometry.h
index 15f1e55..74c9d89 100644
--- a/src/core/SkGeometry.h
+++ b/src/core/SkGeometry.h
@@ -235,7 +235,7 @@
      *  Chop this conic into N quads, stored continguously in pts[], where
      *  N = 1 << pow2. The amount of storage needed is (1 + 2 * N)
      */
-    int chopIntoQuadsPOW2(SkPoint pts[], int pow2) const;
+    int SK_WARN_UNUSED_RESULT chopIntoQuadsPOW2(SkPoint pts[], int pow2) const;
 
     bool findXExtrema(SkScalar* t) const;
     bool findYExtrema(SkScalar* t) const;
@@ -384,7 +384,7 @@
         int pow2 = conic.computeQuadPOW2(tol);
         fQuadCount = 1 << pow2;
         SkPoint* pts = fStorage.reset(1 + 2 * fQuadCount);
-        conic.chopIntoQuadsPOW2(pts, pow2);
+        fQuadCount = conic.chopIntoQuadsPOW2(pts, pow2);
         return pts;
     }
 
diff --git a/tests/PathTest.cpp b/tests/PathTest.cpp
index 8f98e6a..ddbc77c 100644
--- a/tests/PathTest.cpp
+++ b/tests/PathTest.cpp
@@ -110,6 +110,20 @@
     canvas->drawPath(path, paint);
 }
 
+// this is a unit test instead of a GM because it doesn't draw anything
+static void test_fuzz_crbug_638223() {
+    auto surface(SkSurface::MakeRasterN32Premul(250, 250));
+    SkCanvas* canvas = surface->getCanvas();
+    SkPath path;
+    path.moveTo(SkBits2Float(0x47452a00), SkBits2Float(0x43211d01));  // 50474, 161.113f
+    path.conicTo(SkBits2Float(0x401c0000), SkBits2Float(0x40680000),
+        SkBits2Float(0x02c25a81), SkBits2Float(0x981a1fa0),
+        SkBits2Float(0x6bf9abea));  // 2.4375f, 3.625f, 2.85577e-37f, -1.992e-24f, 6.03669e+26f
+    SkPaint paint;
+    paint.setAntiAlias(true);
+    canvas->drawPath(path, paint);
+}
+
 /**
  * In debug mode, this path was causing an assertion to fail in
  * SkPathStroker::preJoinTo() and, in Release, the use of an unitialized value.
@@ -4348,4 +4362,5 @@
     test_skbug_3469(reporter);
     test_skbug_3239(reporter);
     test_bounds_crbug_513799(reporter);
+    test_fuzz_crbug_638223();
 }