[M108-LTS] Enforce an upper limit of 715 million path verbs in SkPath.

Bug: chromium:1464215
Change-Id: Iedb7d73fc80de5ffb881b664dd77314cc2c6b108
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/735316
Commit-Queue: John Stiles <johnstiles@google.com>
(cherry picked from commit 0b19a3da2f29b632de0e4cb346a478fc87c595e9)
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/748156
Reviewed-by: John Stiles <johnstiles@google.com>
diff --git a/relnotes/path_715M.md b/relnotes/path_715M.md
new file mode 100644
index 0000000..7be9a40
--- /dev/null
+++ b/relnotes/path_715M.md
@@ -0,0 +1 @@
+SkPath now enforces an upper limit of 715 million path verbs.
diff --git a/src/core/SkPath.cpp b/src/core/SkPath.cpp
index 7caac5c..1a92797 100644
--- a/src/core/SkPath.cpp
+++ b/src/core/SkPath.cpp
@@ -27,6 +27,7 @@
 #include "src/pathops/SkPathOpsPoint.h"
 
 #include <cmath>
+#include <limits.h>
 #include <utility>
 
 struct SkPath_Storage_Equivalent {
@@ -3401,43 +3402,52 @@
 
 SkPathVerbAnalysis sk_path_analyze_verbs(const uint8_t vbs[], int verbCount) {
     SkPathVerbAnalysis info = {false, 0, 0, 0};
-
     bool needMove = true;
     bool invalid = false;
-    for (int i = 0; i < verbCount; ++i) {
-        switch ((SkPathVerb)vbs[i]) {
-            case SkPathVerb::kMove:
-                needMove = false;
-                info.points += 1;
-                break;
-            case SkPathVerb::kLine:
-                invalid |= needMove;
-                info.segmentMask |= kLine_SkPathSegmentMask;
-                info.points += 1;
-                break;
-            case SkPathVerb::kQuad:
-                invalid |= needMove;
-                info.segmentMask |= kQuad_SkPathSegmentMask;
-                info.points += 2;
-                break;
-            case SkPathVerb::kConic:
-                invalid |= needMove;
-                info.segmentMask |= kConic_SkPathSegmentMask;
-                info.points += 2;
-                info.weights += 1;
-                break;
-            case SkPathVerb::kCubic:
-                invalid |= needMove;
-                info.segmentMask |= kCubic_SkPathSegmentMask;
-                info.points += 3;
-                break;
-            case SkPathVerb::kClose:
-                invalid |= needMove;
-                needMove = true;
-                break;
-            default:
-                invalid = true;
-                break;
+
+    if (verbCount >= (INT_MAX / 3)) {
+        // A path with an extremely high number of quad, conic or cubic verbs could cause
+        // `info.points` to overflow. To prevent against this, we reject extremely large paths. This
+        // check is conservative and assumes the worst case (in particular, it assumes that every
+        // verb consumes 3 points, which would only happen for a path composed entirely of cubics).
+        // This limits us to 700 million verbs, which is large enough for any reasonable use case.
+        invalid = true;
+    } else {
+        for (int i = 0; i < verbCount; ++i) {
+            switch ((SkPathVerb)vbs[i]) {
+                case SkPathVerb::kMove:
+                    needMove = false;
+                    info.points += 1;
+                    break;
+                case SkPathVerb::kLine:
+                    invalid |= needMove;
+                    info.segmentMask |= kLine_SkPathSegmentMask;
+                    info.points += 1;
+                    break;
+                case SkPathVerb::kQuad:
+                    invalid |= needMove;
+                    info.segmentMask |= kQuad_SkPathSegmentMask;
+                    info.points += 2;
+                    break;
+                case SkPathVerb::kConic:
+                    invalid |= needMove;
+                    info.segmentMask |= kConic_SkPathSegmentMask;
+                    info.points += 2;
+                    info.weights += 1;
+                    break;
+                case SkPathVerb::kCubic:
+                    invalid |= needMove;
+                    info.segmentMask |= kCubic_SkPathSegmentMask;
+                    info.points += 3;
+                    break;
+                case SkPathVerb::kClose:
+                    invalid |= needMove;
+                    needMove = true;
+                    break;
+                default:
+                    invalid = true;
+                    break;
+            }
         }
     }
     info.valid = !invalid;