aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar fmalita <fmalita@chromium.org>2016-09-20 06:55:16 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-09-20 06:55:16 -0700
commit6d7e4e83035845e87c7972af2e7b635c0a5afbb0 (patch)
tree4fc49b99345ae40497f0ccefb36e88d2e1209a0c /src
parent16b15ddd4d33302fc459d0d1ee97658291d559b9 (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.cpp10
-rw-r--r--src/effects/gradients/SkGradientShader.cpp2
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));