Handle overflow of accumulated rect perimeter in SkDaskPath cull_path

The fuzzer test case was:

-15,-11  ------> huge,-11
   ^                |
   |                v
-15,5000 <------ huge,5000

where the 'huge' x-value caused the accumulated perimeter to overflow.

Bug:1175370, skia:11307

Change-Id: Ic6760d38c29c440d2d4fcb225a5c556e56a992f6
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/368317
Commit-Queue: Robert Phillips <robertphillips@google.com>
Reviewed-by: Mike Reed <reed@google.com>
diff --git a/src/utils/SkDashPath.cpp b/src/utils/SkDashPath.cpp
index f8612f4..64a6db6 100644
--- a/src/utils/SkDashPath.cpp
+++ b/src/utils/SkDashPath.cpp
@@ -191,12 +191,13 @@
         SkPoint pts[4];  // Rects are all moveTo and lineTo, so we'll only use pts[0] and pts[1].
         SkAssertResult(SkPath::kMove_Verb == iter.next(pts));
 
-        SkScalar accum = 0;  // Sum of unculled edge lengths to keep the phase correct.
+        double accum = 0;  // Sum of unculled edge lengths to keep the phase correct.
+                           // Intentionally a double to minimize the risk of overflow and drift.
         while (iter.next(pts) == SkPath::kLine_Verb) {
             // Notice this vector v and accum work with the original unclipped length.
             SkVector v = pts[1] - pts[0];
 
-            if (clip_line(pts, bounds, intervalLength, SkScalarMod(accum, intervalLength))) {
+            if (clip_line(pts, bounds, intervalLength, std::fmod(accum, intervalLength))) {
                 // pts[0] may have just been changed by clip_line().
                 // If that's not where we ended the previous lineTo(), we need to moveTo() there.
                 SkPoint last;