Bug 1339637 - fix overflow in SkClampRange::init(). r=jrmuizel
authorLee Salzman <lsalzman@mozilla.com>
Tue, 21 Feb 2017 14:32:39 -0500
changeset 344008 8568a8c74f309df44b773d3db3444c928403fdf7
parent 344007 a79f71b7d7a3e3d0189b9bcd801ee76548ddcc70
child 344009 fc14157949746f4f5b902e2f1500589a5f60e401
push id87261
push userlsalzman@mozilla.com
push dateTue, 21 Feb 2017 19:33:19 +0000
treeherdermozilla-inbound@8568a8c74f30 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs1339637
milestone54.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1339637 - fix overflow in SkClampRange::init(). r=jrmuizel MozReview-Commit-ID: 7NtQP5QPsFk
gfx/skia/skia/src/effects/gradients/SkClampRange.cpp
--- a/gfx/skia/skia/src/effects/gradients/SkClampRange.cpp
+++ b/gfx/skia/skia/src/effects/gradients/SkClampRange.cpp
@@ -28,16 +28,31 @@ static bool sk_64_smul_check(int64_t a, 
     // Since we are looking at 64x64 muls, we add 32 to the check.
     if (zeros < (32 + 34)) {
         return false;
     }
     *result = a * b;
     return true;
 }
 
+static bool sk_64_sadd_check(int64_t a, int64_t b, int64_t* result) {
+    if (a > 0) {
+        if (b > std::numeric_limits<int64_t>::max() - a) {
+            return false;
+        }
+    } else {
+        if (b < std::numeric_limits<int64_t>::min() - a) {
+            return false;
+        }
+    }
+
+    *result = a + b;
+    return true;
+}
+
 /*
  *  returns [0..count] for the number of steps (<= count) for which x0 <= edge
  *  given each step is followed by x0 += dx
  */
 static int chop(int64_t x0, SkGradFixed edge, int64_t x1, int64_t dx, int count) {
     SkASSERT(dx > 0);
     SkASSERT(count >= 0);
 
@@ -77,26 +92,25 @@ void SkClampRange::init(SkGradFixed fx0,
         this->initFor1(fx0);
         return;
     }
 
     int64_t fx = fx0;
     int64_t dx = dx0;
 
     // start with ex equal to the last computed value
-    int64_t count_times_dx;
-    if (!sk_64_smul_check(count - 1, dx, &count_times_dx)) {
+    int64_t count_times_dx, ex;
+    if (!sk_64_smul_check(count - 1, dx, &count_times_dx) ||
+        !sk_64_sadd_check(fx, count_times_dx, &ex)) {
         // we can't represent the computed end in 32.32, so just draw something (first color)
         fCount1 = fCount2 = 0;
         fCount0 = count;
         return;
     }
 
-    int64_t ex = fx + (count - 1) * dx;
-
     if ((uint64_t)(fx | ex) <= kFracMax_SkGradFixed) {
         fCount0 = fCount2 = 0;
         fCount1 = count;
         fFx1 = fx0;
         return;
     }
     if (fx <= 0 && ex <= 0) {
         fCount1 = fCount2 = 0;