From 06196411cb3e06bd041b7ec12e69d0a7a790d5b7 Mon Sep 17 00:00:00 2001 From: Yuqian Li Date: Mon, 14 Nov 2016 16:45:01 -0500 Subject: [PATCH] Catch width overflow in ASAN using int64 This is related with our previous CL: https://skia-review.googlesource.com/c/4628/ That previous CL fix won't pass the ASAN test (../../../include/core/SkRect.h:72:39: runtime error: signed integer overflow: 1 - -2147483648 cannot be represented in type 'int') so we use int64 in this CL. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=4785 Change-Id: I39f7329c427d49f4be07588f37120722ac9892c2 Reviewed-on: https://skia-review.googlesource.com/4785 Reviewed-by: Mike Reed --- src/core/SkScan_AAAPath.cpp | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/core/SkScan_AAAPath.cpp b/src/core/SkScan_AAAPath.cpp index 8ca2fea714..3915feae59 100644 --- a/src/core/SkScan_AAAPath.cpp +++ b/src/core/SkScan_AAAPath.cpp @@ -153,8 +153,7 @@ public: int getWidth() override { return fClipRect.width(); } static bool canHandleRect(const SkIRect& bounds) { - // The width may overflow signed int, e.g., left = -2147483648, right = 1 - unsigned width = bounds.width(); + int width = bounds.width(); if (width > MaskAdditiveBlitter::kMAX_WIDTH) { return false; } @@ -1251,6 +1250,22 @@ static int rect_overflows_short_shift(SkIRect rect, int shift) { overflows_short_shift(rect.fBottom, 2); } +static bool fitsInsideLimit(const SkRect& r, SkScalar max) { + const SkScalar min = -max; + return r.fLeft > min && r.fTop > min && + r.fRight < max && r.fBottom < max; +} + +static bool safeRoundOut(const SkRect& src, SkIRect* dst, int32_t maxInt) { + const SkScalar maxScalar = SkIntToScalar(maxInt); + + if (fitsInsideLimit(src, maxScalar)) { + src.roundOut(dst); + return true; + } + return false; +} + void SkScan::AAAFillPath(const SkPath& path, const SkRegion& origClip, SkBlitter* blitter, bool forceRLE) { if (origClip.isEmpty()) { @@ -1264,7 +1279,9 @@ void SkScan::AAAFillPath(const SkPath& path, const SkRegion& origClip, SkBlitter const bool isInverse = path.isInverseFillType(); SkIRect ir; - path.getBounds().roundOut(&ir); + if (!safeRoundOut(path.getBounds(), &ir, SK_MaxS32 >> 2)) { + return; + } if (ir.isEmpty()) { if (isInverse) { blitter->blitRegion(origClip);