diff options
author | Mike Reed <reed@google.com> | 2018-04-30 17:05:15 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-05-01 15:29:14 +0000 |
commit | dc3192b30a9e42aea8ff8d0c01ea585c79902704 (patch) | |
tree | 32324a64ed2846e9ccf81980f777e3178b8c52c9 /src/core/SkRegion.cpp | |
parent | ff8387fae47e482c6f78865deb2746618a51fa51 (diff) |
pin offset request before applying to region
Bug: oss-fuzz:8085
Change-Id: I2e19250822a6ffc3d68a474c8eb4cca0ea66c991
Reviewed-on: https://skia-review.googlesource.com/124700
Reviewed-by: Mike Klein <mtklein@google.com>
Commit-Queue: Mike Reed <reed@google.com>
Diffstat (limited to 'src/core/SkRegion.cpp')
-rw-r--r-- | src/core/SkRegion.cpp | 21 |
1 files changed, 18 insertions, 3 deletions
diff --git a/src/core/SkRegion.cpp b/src/core/SkRegion.cpp index bf06e747db..080b148e47 100644 --- a/src/core/SkRegion.cpp +++ b/src/core/SkRegion.cpp @@ -574,6 +574,16 @@ bool SkRegion::operator==(const SkRegion& b) const { ah->fRunCount * sizeof(SkRegion::RunType)); } +// Return a (new) offset such that when applied (+=) to min and max, we don't overflow/underflow +static int32_t pin_offset_s32(int32_t min, int32_t max, int32_t offset) { + SkASSERT(min <= max); + const int32_t lo = -SK_MaxS32-1, + hi = +SK_MaxS32; + if ((int64_t)min + offset < lo) { offset = lo - min; } + if ((int64_t)max + offset > hi) { offset = hi - max; } + return offset; +} + void SkRegion::translate(int dx, int dy, SkRegion* dst) const { SkDEBUGCODE(this->validate();) @@ -582,9 +592,14 @@ void SkRegion::translate(int dx, int dy, SkRegion* dst) const { } if (this->isEmpty()) { dst->setEmpty(); - } else if (this->isRect()) { - dst->setRect(fBounds.fLeft + dx, fBounds.fTop + dy, - fBounds.fRight + dx, fBounds.fBottom + dy); + return; + } + // pin dx and dy so we don't overflow our existing bounds + dx = pin_offset_s32(fBounds.fLeft, fBounds.fRight, dx); + dy = pin_offset_s32(fBounds.fTop, fBounds.fBottom, dy); + + if (this->isRect()) { + dst->setRect(fBounds.makeOffset(dx, dy)); } else { if (this == dst) { dst->fRunHead = dst->fRunHead->ensureWritable(); |