From 20079a94e82fd7345dfb119a8777e5ba482a041c Mon Sep 17 00:00:00 2001 From: Yuqian Li Date: Wed, 16 Nov 2016 13:07:57 -0500 Subject: [PATCH] Fix mask overflow caused by edge drift BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=4797 Change-Id: Ica1568b67c1e1ce4aae2bdaba2c5b1f2155d1382 Reviewed-on: https://skia-review.googlesource.com/4797 Reviewed-by: Cary Clark --- src/core/SkAnalyticEdge.h | 2 +- src/core/SkScan_AAAPath.cpp | 12 +++++++++++- tests/PathTest.cpp | 19 +++++++++++++++++++ 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/core/SkAnalyticEdge.h b/src/core/SkAnalyticEdge.h index 00812866d5..a55ab2a71e 100644 --- a/src/core/SkAnalyticEdge.h +++ b/src/core/SkAnalyticEdge.h @@ -44,7 +44,7 @@ struct SkAnalyticEdge { static inline SkFixed snapY(SkFixed y, int accuracy = kDefaultAccuracy) { // This approach is safer than left shift, round, then right shift - return (y + (SK_Fixed1 >> (accuracy + 1))) >> (16 - accuracy) << (16 - accuracy); + return ((unsigned)y + (SK_Fixed1 >> (accuracy + 1))) >> (16 - accuracy) << (16 - accuracy); } // Update fX, fY of this edge so fY = y diff --git a/src/core/SkScan_AAAPath.cpp b/src/core/SkScan_AAAPath.cpp index 8bfe7bbb1b..47d2dcc1bf 100644 --- a/src/core/SkScan_AAAPath.cpp +++ b/src/core/SkScan_AAAPath.cpp @@ -1204,8 +1204,18 @@ void aaa_fill_path(const SkPath& path, const SkIRect& clipRect, AdditiveBlitter* if (!path.isInverseFillType() && path.isConvex()) { SkASSERT(count >= 2); // convex walker does not handle missing right edges + SkFixed leftBound = SkIntToFixed(rect.fLeft); + SkFixed rightBound = SkIntToFixed(rect.fRight); + if (isUsingMask) { + // If we're using mask, then we have to limit the bound within the path bounds. + // Otherwise, the edge drift may access an invalid address inside the mask. + SkIRect ir; + path.getBounds().roundOut(&ir); + leftBound = SkTMax(leftBound, SkIntToFixed(ir.fLeft)); + rightBound = SkTMin(rightBound, SkIntToFixed(ir.fRight)); + } aaa_walk_convex_edges(&headEdge, blitter, start_y, stop_y, - rect.fLeft << 16, rect.fRight << 16, isUsingMask); + leftBound, rightBound, isUsingMask); } else { SkFAIL("Concave AAA is not yet implemented!"); } diff --git a/tests/PathTest.cpp b/tests/PathTest.cpp index 85bd804874..f064a16f77 100644 --- a/tests/PathTest.cpp +++ b/tests/PathTest.cpp @@ -198,6 +198,24 @@ static void test_fuzz_crbug_662780() { canvas->drawRectCoords(0, 0, 250, 250, paint); } +static void test_mask_overflow() { + auto surface(SkSurface::MakeRasterN32Premul(500, 500)); + SkCanvas* canvas = surface->getCanvas(); + SkPaint paint; + paint.setAntiAlias(true); + SkPath path; + path.moveTo(SkBits2Float(0x43e28000), SkBits2Float(0x43aa8000)); // 453, 341 + path.lineTo(SkBits2Float(0x43de6000), SkBits2Float(0x43aa8000)); // 444.75f, 341 + // 440.47f, 341, 437, 344.47f, 437, 348.75f + path.cubicTo(SkBits2Float(0x43dc3c29), SkBits2Float(0x43aa8000), + SkBits2Float(0x43da8000), SkBits2Float(0x43ac3c29), + SkBits2Float(0x43da8000), SkBits2Float(0x43ae6000)); + path.lineTo(SkBits2Float(0x43da8000), SkBits2Float(0x43b18000)); // 437, 355 + path.lineTo(SkBits2Float(0x43e28000), SkBits2Float(0x43b18000)); // 453, 355 + path.lineTo(SkBits2Float(0x43e28000), SkBits2Float(0x43aa8000)); // 453, 341 + canvas->drawPath(path, paint); +} + /** * In debug mode, this path was causing an assertion to fail in * SkPathStroker::preJoinTo() and, in Release, the use of an unitialized value. @@ -4359,6 +4377,7 @@ DEF_TEST(Paths, reporter) { test_fuzz_crbug_662952(reporter); test_fuzz_crbug_662730(reporter); test_fuzz_crbug_662780(); + test_mask_overflow(); SkTSize::Make(3,4);