diff options
author | Cary Clark <caryclark@skia.org> | 2018-03-21 16:17:10 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-04-02 15:15:25 +0000 |
commit | 9b8b0cee513bc242553f1639a28c3638f568842e (patch) | |
tree | 3c5efc4f728fefa532f2e8a5583c6ee57a9dd59b /src/core | |
parent | 01a1cf92603c048c81dec419177e4e5f76be50f6 (diff) |
fix SkRRect fuzzer assert
fuzzer bug triggers an assert in SkRRect::isValid because
on radius is zero and the other, while small, is not.
The radii are normally both set to zero if one is zero
in SkRRect::setRectRadii. However, subsequently scaleRadii
may set one to zero when normalizing the pair.
Move the clamping code out of setRectRadii so it can be
called from scaleRadii as well.
R=reed@google.com
Bug: skia:
Change-Id: Ib9a86da7212567b2f4b83d99a41cf9ba2c30e9b9
Reviewed-on: https://skia-review.googlesource.com/115701
Reviewed-by: Mike Reed <reed@google.com>
Commit-Queue: Cary Clark <caryclark@google.com>
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/SkRRect.cpp | 48 |
1 files changed, 29 insertions, 19 deletions
diff --git a/src/core/SkRRect.cpp b/src/core/SkRRect.cpp index a8ed7246ef..50a87fab3c 100644 --- a/src/core/SkRRect.cpp +++ b/src/core/SkRRect.cpp @@ -116,40 +116,44 @@ static double compute_min_scale(double rad1, double rad2, double limit, double c return curMin; } -void SkRRect::setRectRadii(const SkRect& rect, const SkVector radii[4]) { - if (!this->initializeRect(rect)) { - return; - } - - if (!SkScalarsAreFinite(&radii[0].fX, 8)) { - this->setRect(rect); // devolve into a simple rect - return; - } - - memcpy(fRadii, radii, sizeof(fRadii)); - +static bool clamp_to_zero(SkVector radii[4]) { bool allCornersSquare = true; // Clamp negative radii to zero for (int i = 0; i < 4; ++i) { - if (fRadii[i].fX <= 0 || fRadii[i].fY <= 0) { + if (radii[i].fX <= 0 || radii[i].fY <= 0) { // In this case we are being a little fast & loose. Since one of // the radii is 0 the corner is square. However, the other radii // could still be non-zero and play in the global scale factor // computation. - fRadii[i].fX = 0; - fRadii[i].fY = 0; + radii[i].fX = 0; + radii[i].fY = 0; } else { allCornersSquare = false; } } - if (allCornersSquare) { + return allCornersSquare; +} + +void SkRRect::setRectRadii(const SkRect& rect, const SkVector radii[4]) { + if (!this->initializeRect(rect)) { + return; + } + + if (!SkScalarsAreFinite(&radii[0].fX, 8)) { + this->setRect(rect); // devolve into a simple rect + return; + } + + memcpy(fRadii, radii, sizeof(fRadii)); + + if (clamp_to_zero(fRadii)) { this->setRect(rect); return; } - this->scaleRadii(); + this->scaleRadii(rect); } bool SkRRect::initializeRect(const SkRect& rect) { @@ -167,7 +171,7 @@ bool SkRRect::initializeRect(const SkRect& rect) { return true; } -void SkRRect::scaleRadii() { +void SkRRect::scaleRadii(const SkRect& rect) { // Proportionally scale down all radii to fit. Find the minimum ratio // of a side and the radii on that side (for all four sides) and use @@ -196,6 +200,12 @@ void SkRRect::scaleRadii() { SkScaleToSides::AdjustRadii(height, scale, &fRadii[3].fY, &fRadii[0].fY); } + // adjust radii may set x or y to zero; set companion to zero as well + if (clamp_to_zero(fRadii)) { + this->setRect(rect); + return; + } + // At this point we're either oval, simple, or complex (not empty or rect). this->computeType(); @@ -440,7 +450,7 @@ bool SkRRect::transform(const SkMatrix& matrix, SkRRect* dst) const { return false; } - dst->scaleRadii(); + dst->scaleRadii(dst->fRect); dst->isValid(); return true; |