diff options
author | reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-08-06 14:58:35 +0000 |
---|---|---|
committer | reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-08-06 14:58:35 +0000 |
commit | d9ee348720f933d8a23547ee36693880296810c5 (patch) | |
tree | f69c3ac71aa10a182360c9c5b514e26da4e63da1 /src/effects | |
parent | 157d94465a47a57e30e5cf49cd57dccd903e27e2 (diff) |
If we lose precision computing sum of the dash intervals, then we can have the
same error when we subtract-in-a-loop with the phase. The result is that we can
read past the end of the array.
To fix this, we just pin the loop counter, and if we exhaust our intervals, we
just treat the phase as 0. Not precisely the exact answer, but we aren't going
to draw this dash correctly anyway, since it contains massive interval values
that will be imprecise given our current float implementation.
Fixes http://code.google.com/p/chromium/issues/detail?id=140642
Review URL: https://codereview.appspot.com/6458088
git-svn-id: http://skia.googlecode.com/svn/trunk@4959 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/effects')
-rw-r--r-- | src/effects/SkDashPathEffect.cpp | 24 |
1 files changed, 16 insertions, 8 deletions
diff --git a/src/effects/SkDashPathEffect.cpp b/src/effects/SkDashPathEffect.cpp index e6f6afaf07..c1bb705818 100644 --- a/src/effects/SkDashPathEffect.cpp +++ b/src/effects/SkDashPathEffect.cpp @@ -16,14 +16,21 @@ static inline int is_even(int x) { } static SkScalar FindFirstInterval(const SkScalar intervals[], SkScalar phase, - int32_t* index) { - int i; - - for (i = 0; phase > intervals[i]; i++) { - phase -= intervals[i]; + int32_t* index, int count) { + for (int i = 0; i < count; ++i) { + if (phase > intervals[i]) { + phase -= intervals[i]; + } else { + *index = i; + return intervals[i] - phase; + } } - *index = i; - return intervals[i] - phase; + // If we get here, phase "appears" to be larger than our length. This + // shouldn't happen with perfect precision, but we can accumulate errors + // during the initial length computation (rounding can make our sum be too + // big or too small. In that event, we just have to eat the error here. + *index = 0; + return intervals[0]; } SkDashPathEffect::SkDashPathEffect(const SkScalar intervals[], int count, @@ -67,7 +74,8 @@ SkDashPathEffect::SkDashPathEffect(const SkScalar intervals[], int count, } SkASSERT(phase >= 0 && phase < len); - fInitialDashLength = FindFirstInterval(intervals, phase, &fInitialDashIndex); + fInitialDashLength = FindFirstInterval(intervals, phase, + &fInitialDashIndex, count); SkASSERT(fInitialDashLength >= 0); SkASSERT(fInitialDashIndex >= 0 && fInitialDashIndex < fCount); |