diff options
author | fmalita <fmalita@chromium.org> | 2016-09-20 06:55:16 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-09-20 06:55:16 -0700 |
commit | 6d7e4e83035845e87c7972af2e7b635c0a5afbb0 (patch) | |
tree | 4fc49b99345ae40497f0ccefb36e88d2e1209a0c /src | |
parent | 16b15ddd4d33302fc459d0d1ee97658291d559b9 (diff) |
Harden LinearGradient4fContext
Three distinct issues exposed by Fuzzer:
1) truncating the flags to 8 bits may trip the assert in SkToU8
Since clients can pass in any garbage, we cannot assume it fits in 8
bits. Just static_cast<> instead.
2) vertical gradients with dx == -0.0 don't trigger interval inversion.
For dx < 0 we want reversed intervals. But, alas, -0.0 < 0 == false
(thanks, Ob^WIEEE 754!). Use signbit() instead.
3) half closed range checking needs to be inverted for reversed
intervals.
Normally we check for [p0, p1), but for reversed intervals (p1 < p0) we
want to check for [p1, p0), and not (p1, p0]. Adjust the logic
accordingly.
BUG=skia:5647
R=reed@google.com,kjlubick@google.com
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2349153004
Review-Url: https://codereview.chromium.org/2349153004
Diffstat (limited to 'src')
-rw-r--r-- | src/effects/gradients/Sk4fLinearGradient.cpp | 10 | ||||
-rw-r--r-- | src/effects/gradients/SkGradientShader.cpp | 2 |
2 files changed, 7 insertions, 5 deletions
diff --git a/src/effects/gradients/Sk4fLinearGradient.cpp b/src/effects/gradients/Sk4fLinearGradient.cpp index dc6e530a0c..cd1f770ef9 100644 --- a/src/effects/gradients/Sk4fLinearGradient.cpp +++ b/src/effects/gradients/Sk4fLinearGradient.cpp @@ -100,12 +100,13 @@ SkScalar pinFx<SkShader::kMirror_TileMode>(SkScalar fx) { return f < 0 ? f + 2 : f; } -// true when x is in [k1,k2) +// true when x is in [k1,k2), or [k2, k1) when the interval is reversed. +// TODO(fmalita): hoist the reversed interval check out of this helper. bool in_range(SkScalar x, SkScalar k1, SkScalar k2) { SkASSERT(k1 != k2); return (k1 < k2) - ? (x >= k1 && x < k2) - : (x >= k2 && x < k1); + ? (x >= k1 && x < k2) + : (x > k2 && x <= k1); } } // anonymous namespace @@ -116,7 +117,7 @@ LinearGradient4fContext::LinearGradient4fContext(const SkLinearGradient& shader, : INHERITED(shader, rec) { // Our fast path expects interval points to be monotonically increasing in x. - const bool reverseIntervals = this->isFast() && fDstToPos.getScaleX() < 0; + const bool reverseIntervals = this->isFast() && signbit(fDstToPos.getScaleX()); this->buildIntervals(shader, rec, reverseIntervals); SkASSERT(fIntervals.count() > 0); @@ -290,6 +291,7 @@ public: , fDx(dx) , fIsVertical(is_vertical) { + SkASSERT(fAdvX >= 0); SkASSERT(firstInterval <= lastInterval); SkASSERT(in_range(fx, i->fP0, i->fP1)); this->compute_interval_props(fx - i->fP0); diff --git a/src/effects/gradients/SkGradientShader.cpp b/src/effects/gradients/SkGradientShader.cpp index 3a28da8099..4f174d72b9 100644 --- a/src/effects/gradients/SkGradientShader.cpp +++ b/src/effects/gradients/SkGradientShader.cpp @@ -76,7 +76,7 @@ SkGradientShaderBase::SkGradientShaderBase(const Descriptor& desc, const SkMatri fPtsToUnit.getType(); // Precache so reads are threadsafe. SkASSERT(desc.fCount > 1); - fGradFlags = SkToU8(desc.fGradFlags); + fGradFlags = static_cast<uint8_t>(desc.fGradFlags); SkASSERT((unsigned)desc.fTileMode < SkShader::kTileModeCount); SkASSERT(SkShader::kTileModeCount == SK_ARRAY_COUNT(gTileProcs)); |