diff options
author | Florin Malita <fmalita@chromium.org> | 2016-12-13 09:42:20 -0500 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2016-12-13 15:22:27 +0000 |
commit | 72245c522ab65593239f2056df16082edb4e0a2e (patch) | |
tree | 3783f55914859d1c317b58126521a7c851cfa822 | |
parent | 941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9 (diff) |
Avoid int64 overflow in SkClampRange
Update sk_64_smul_check to detect the numeric_limits<int64_t>::min()
case (which cannot be safely passed to SkTAbs), and fail.
BUG=skia:6019
R=reed@google.com,mtklein@google.com
Change-Id: I5f252be7e9377d3261f992b53f2b893899cbe960
Reviewed-on: https://skia-review.googlesource.com/5863
Reviewed-by: Mike Klein <mtklein@chromium.org>
Commit-Queue: Florin Malita <fmalita@chromium.org>
-rw-r--r-- | src/effects/gradients/SkClampRange.cpp | 15 |
1 files changed, 10 insertions, 5 deletions
diff --git a/src/effects/gradients/SkClampRange.cpp b/src/effects/gradients/SkClampRange.cpp index 5fd1c0369e..f820a03710 100644 --- a/src/effects/gradients/SkClampRange.cpp +++ b/src/effects/gradients/SkClampRange.cpp @@ -18,18 +18,23 @@ static int SkCLZ64(uint64_t value) { return count + SkCLZ(SkToU32(value)); } -static bool sk_64_smul_check(int64_t a, int64_t b, int64_t* result) { +static bool sk_64_smul_check(int64_t count, int64_t dx, int64_t* result) { // Do it the slow way until we have some assembly. - int64_t ua = SkTAbs(a); - int64_t ub = SkTAbs(b); - int zeros = SkCLZ64(ua) + SkCLZ64(ub); + if (dx == std::numeric_limits<int64_t>::min()) { + return false; // SkTAbs overflow + } + + SkASSERT(count >= 0); + uint64_t ucount = static_cast<uint64_t>(count); + uint64_t udx = static_cast<uint64_t>(SkTAbs(dx)); + int zeros = SkCLZ64(ucount) + SkCLZ64(udx); // this is a conservative check: it may return false when in fact it would not have overflowed. // Hackers Delight uses 34 as its convervative check, but that is for 32x32 multiplies. // Since we are looking at 64x64 muls, we add 32 to the check. if (zeros < (32 + 34)) { return false; } - *result = a * b; + *result = count * dx; return true; } |