Fix some overflowing integers in SkPolyUtils

Bug: oss-fuzz:10293
Change-Id: If3a98e60081ebef7bdc8460fce4fa682245c68cc
Reviewed-on: https://skia-review.googlesource.com/153661
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Jim Van Verth <jvanverth@google.com>
diff --git a/src/utils/SkPolyUtils.cpp b/src/utils/SkPolyUtils.cpp
index 06e8546..5bf8e3e 100644
--- a/src/utils/SkPolyUtils.cpp
+++ b/src/utils/SkPolyUtils.cpp
@@ -7,6 +7,8 @@
 
 #include "SkPolyUtils.h"
 
+#include <limits>
+
 #include "SkPointPriv.h"
 #include "SkTArray.h"
 #include "SkTemplates.h"
@@ -309,7 +311,7 @@
 
     // restrict this to match other routines
     // practically we don't want anything bigger than this anyway
-    if (inputPolygonSize >= (1 << 16)) {
+    if (inputPolygonSize > std::numeric_limits<uint16_t>::max()) {
         return false;
     }
 
@@ -346,11 +348,12 @@
     OffsetEdge* currEdge = head;
     OffsetEdge* prevEdge = currEdge->fPrev;
     int insetVertexCount = inputPolygonSize;
-    int iterations = 0;
+    unsigned int iterations = 0;
+    unsigned int maxIterations = inputPolygonSize * inputPolygonSize;
     while (head && prevEdge != currEdge) {
         ++iterations;
         // we should check each edge against each other edge at most once
-        if (iterations > inputPolygonSize*inputPolygonSize) {
+        if (iterations > maxIterations) {
             return false;
         }
 
@@ -406,30 +409,31 @@
     // store all the valid intersections that aren't nearly coincident
     // TODO: look at the main algorithm and see if we can detect these better
     insetPolygon->reset();
-    if (head) {
-        static constexpr SkScalar kCleanupTolerance = 0.01f;
-        if (insetVertexCount >= 0) {
-            insetPolygon->setReserve(insetVertexCount);
+    if (!head) {
+        return false;
+    }
+
+    static constexpr SkScalar kCleanupTolerance = 0.01f;
+    if (insetVertexCount >= 0) {
+        insetPolygon->setReserve(insetVertexCount);
+    }
+    int currIndex = 0;
+    *insetPolygon->push() = head->fIntersection;
+    currEdge = head->fNext;
+    while (currEdge != head) {
+        if (!SkPointPriv::EqualsWithinTolerance(currEdge->fIntersection,
+                                                (*insetPolygon)[currIndex],
+                                                kCleanupTolerance)) {
+            *insetPolygon->push() = currEdge->fIntersection;
+            currIndex++;
         }
-        int currIndex = 0;
-        OffsetEdge* currEdge = head;
-        *insetPolygon->push() = currEdge->fIntersection;
         currEdge = currEdge->fNext;
-        while (currEdge != head) {
-            if (!SkPointPriv::EqualsWithinTolerance(currEdge->fIntersection,
-                                                    (*insetPolygon)[currIndex],
-                                                    kCleanupTolerance)) {
-                *insetPolygon->push() = currEdge->fIntersection;
-                currIndex++;
-            }
-            currEdge = currEdge->fNext;
-        }
-        // make sure the first and last points aren't coincident
-        if (currIndex >= 1 &&
-           SkPointPriv::EqualsWithinTolerance((*insetPolygon)[0], (*insetPolygon)[currIndex],
-                                              kCleanupTolerance)) {
-            insetPolygon->pop();
-        }
+    }
+    // make sure the first and last points aren't coincident
+    if (currIndex >= 1 &&
+        SkPointPriv::EqualsWithinTolerance((*insetPolygon)[0], (*insetPolygon)[currIndex],
+                                            kCleanupTolerance)) {
+        insetPolygon->pop();
     }
 
     return SkIsConvexPolygon(insetPolygon->begin(), insetPolygon->count());
@@ -455,7 +459,7 @@
     SkScalar floatSteps = SkScalarAbs(offset*theta*kRecipPixelsPerArcSegment);
     // limit the number of steps to at most max uint16_t (that's all we can index)
     // knock one value off the top to account for rounding
-    if (floatSteps >= (1 << 16)-1) {
+    if (floatSteps >= std::numeric_limits<uint16_t>::max()) {
         return false;
     }
     int steps = SkScalarRoundToInt(floatSteps);
@@ -1029,7 +1033,7 @@
     }
 
     // need to be able to represent all the vertices in the 16-bit indices
-    if (polygonSize >= (1 << 16)) {
+    if (polygonSize > std::numeric_limits<uint16_t>::max()) {
         return false;
     }
 
@@ -1129,7 +1133,7 @@
     }
 
     // need to be able to represent all the vertices in the 16-bit indices
-    if (inputPolygonSize >= (1 << 16)) {
+    if (inputPolygonSize >= std::numeric_limits<uint16_t>::max()) {
         return false;
     }
 
@@ -1145,7 +1149,7 @@
 
     // build normals
     SkAutoSTMalloc<64, SkVector> normals(inputPolygonSize);
-    int numEdges = 0;
+    unsigned int numEdges = 0;
     for (int currIndex = 0, prevIndex = inputPolygonSize - 1;
          currIndex < inputPolygonSize;
          prevIndex = currIndex, ++currIndex) {
@@ -1181,6 +1185,13 @@
         numEdges += SkTMax(numSteps, 1);
     }
 
+    // Make sure we don't overflow the max array count.
+    // We shouldn't overflow numEdges, as SkComputeRadialSteps returns a max of 2^16-1,
+    // and we have a max of 2^16-1 original vertices.
+    if (numEdges > (unsigned int)std::numeric_limits<int32_t>::max()) {
+        return false;
+    }
+
     // build initial offset edge list
     SkSTArray<64, OffsetEdge> edgeData(numEdges);
     OffsetEdge* prevEdge = nullptr;
@@ -1243,15 +1254,16 @@
     edgeData[0].fPrev = prevEdge;
 
     // now clip edges
-    SkASSERT(edgeData.count() == numEdges);
+    SkASSERT(edgeData.count() == (int)numEdges);
     auto head = &edgeData[0];
     auto currEdge = head;
-    int offsetVertexCount = numEdges;
-    int iterations = 0;
-    while (head && prevEdge != currEdge) {
+    unsigned int offsetVertexCount = numEdges;
+    unsigned long long iterations = 0;
+    unsigned long long maxIterations = (unsigned long long)(numEdges*numEdges);
+    while (head && prevEdge != currEdge && offsetVertexCount > 0) {
         ++iterations;
         // we should check each edge against each other edge at most once
-        if (iterations > numEdges*numEdges) {
+        if (iterations > maxIterations) {
             return false;
         }
 
@@ -1327,38 +1339,38 @@
     // store all the valid intersections that aren't nearly coincident
     // TODO: look at the main algorithm and see if we can detect these better
     offsetPolygon->reset();
-    if (head) {
-        static constexpr SkScalar kCleanupTolerance = 0.01f;
-        if (offsetVertexCount >= 0) {
-            offsetPolygon->setReserve(offsetVertexCount);
-        }
-        int currIndex = 0;
-        OffsetEdge* currEdge = head;
-        *offsetPolygon->push() = currEdge->fIntersection;
-        if (polygonIndices) {
-            *polygonIndices->push() = currEdge->fIndex;
+    if (!head || offsetVertexCount == 0 ||
+        offsetVertexCount >= std::numeric_limits<uint16_t>::max()) {
+        return false;
+    }
+
+    static constexpr SkScalar kCleanupTolerance = 0.01f;
+    offsetPolygon->setReserve(offsetVertexCount);
+    int currIndex = 0;
+    *offsetPolygon->push() = head->fIntersection;
+    if (polygonIndices) {
+        *polygonIndices->push() = head->fIndex;
+    }
+    currEdge = head->fNext;
+    while (currEdge != head) {
+        if (!SkPointPriv::EqualsWithinTolerance(currEdge->fIntersection,
+                                                (*offsetPolygon)[currIndex],
+                                                kCleanupTolerance)) {
+            *offsetPolygon->push() = currEdge->fIntersection;
+            if (polygonIndices) {
+                *polygonIndices->push() = currEdge->fIndex;
+            }
+            currIndex++;
         }
         currEdge = currEdge->fNext;
-        while (currEdge != head) {
-            if (!SkPointPriv::EqualsWithinTolerance(currEdge->fIntersection,
-                                                    (*offsetPolygon)[currIndex],
-                                                    kCleanupTolerance)) {
-                *offsetPolygon->push() = currEdge->fIntersection;
-                if (polygonIndices) {
-                    *polygonIndices->push() = currEdge->fIndex;
-                }
-                currIndex++;
-            }
-            currEdge = currEdge->fNext;
-        }
-        // make sure the first and last points aren't coincident
-        if (currIndex >= 1 &&
-            SkPointPriv::EqualsWithinTolerance((*offsetPolygon)[0], (*offsetPolygon)[currIndex],
-                                               kCleanupTolerance)) {
-            offsetPolygon->pop();
-            if (polygonIndices) {
-                polygonIndices->pop();
-            }
+    }
+    // make sure the first and last points aren't coincident
+    if (currIndex >= 1 &&
+        SkPointPriv::EqualsWithinTolerance((*offsetPolygon)[0], (*offsetPolygon)[currIndex],
+                                            kCleanupTolerance)) {
+        offsetPolygon->pop();
+        if (polygonIndices) {
+            polygonIndices->pop();
         }
     }
 
@@ -1462,7 +1474,7 @@
         return false;
     }
     // need to be able to represent all the vertices in the 16-bit indices
-    if (polygonSize >= (1 << 16)) {
+    if (polygonSize >= std::numeric_limits<uint16_t>::max()) {
         return false;
     }