[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;