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>
This commit is contained in:
Mike Reed 2018-08-23 12:47:59 -04:00 committed by Skia Commit-Bot
parent ea045b5b76
commit 4c6514490e
2 changed files with 27 additions and 0 deletions

View File

@ -361,6 +361,8 @@ bool SkDashPath::InternalFilter(SkPath* dst, const SkPath& src, SkStrokeRec* rec
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 @@ bool SkDashPath::InternalFilter(SkPath* dst, const SkPath& src, SkStrokeRec* rec
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)) {

View File

@ -123,3 +123,20 @@ DEF_TEST(DashPathEffectTest_asPoints_limit, r) {
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);
}