fix dashimpl underflow
Previous impl would assert (and read past legal memory) for the new test.
Bug: skia: 8274
Bug: 875494
Change-Id: I2a2e20085d54d611151a9e20ae9cebf33c511329
Reviewed-on: https://skia-review.googlesource.com/148940
Commit-Queue: Mike Reed <reed@google.com>
Reviewed-by: Mike Klein <mtklein@google.com>
diff --git a/src/utils/SkDashPath.cpp b/src/utils/SkDashPath.cpp
index fc73c9f..454a8b5 100644
--- a/src/utils/SkDashPath.cpp
+++ b/src/utils/SkDashPath.cpp
@@ -361,6 +361,8 @@
int32_t count, SkScalar initialDashLength, int32_t initialDashIndex,
SkScalar intervalLength,
StrokeRecApplication strokeRecApplication) {
+ // we must always have an even number of intervals
+ SkASSERT(is_even(count));
// we do nothing if the src wants to be filled
SkStrokeRec::Style style = rec->getStyle();
@@ -384,6 +386,14 @@
while (endPhase > intervals[index]) {
endPhase -= intervals[index++];
SkASSERT(index <= count);
+ if (index == count) {
+ // We have run out of intervals. endPhase "should" never get to this point,
+ // but it could if the subtracts underflowed. Hence we will pin it as if it
+ // perfectly ran through the intervals.
+ // See crbug.com/875494 (and skbug.com/8274)
+ endPhase = 0;
+ break;
+ }
}
// if dash ends inside "on", or ends at beginning of "off"
if (is_even(index) == (endPhase > 0)) {
diff --git a/tests/DashPathEffectTest.cpp b/tests/DashPathEffectTest.cpp
index f165207..c50c88d 100644
--- a/tests/DashPathEffectTest.cpp
+++ b/tests/DashPathEffectTest.cpp
@@ -123,3 +123,20 @@
p.setPathEffect(SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), 0));
canvas->drawLine(1, 1, 1, 5.0e10f, p);
}
+
+// This used to cause SkDashImpl to walk off the end of the intervals array, due to underflow
+// trying to substract a smal value from a large one in floats.
+DEF_TEST(DashCrazy_crbug_875494, r) {
+ SkScalar vals[] = { 98, 94, 2888458849.f, 227, 0, 197 };
+ const int N = SK_ARRAY_COUNT(vals);
+
+ SkRect cull = SkRect::MakeXYWH(43,236,57,149);
+ SkPath path;
+ path.addRect(cull);
+
+ SkPath path2;
+ SkPaint paint;
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setPathEffect(SkDashPathEffect::Make(vals, N, 222));
+ paint.getFillPath(path, &path2, &cull);
+}