aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Herb Derby <herb@google.com>2018-02-28 14:03:18 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-03-06 19:56:47 +0000
commit8994150a436f0e813e9a7b8a2dc0ad237f4e3513 (patch)
tree0eccf683220dfe5643d276d83a71592c89dab4d0 /src
parentbe1b3971806e3d80aa9673a36e2b35d0145198ac (diff)
Centralize mask byte calculations
These calculations are usually done in place around the code, but most implementation don't take the care needed for safe calculation. I have provided safe implementations for use around the code. It will take a while to track down all the independant implementations and convert them over. BUG=skia:7515 Change-Id: Ice6a9be2e8e5ebef18d472adb26c17b03177ef47 Reviewed-on: https://skia-review.googlesource.com/111120 Reviewed-by: Mike Reed <reed@google.com> Commit-Queue: Herb Derby <herb@google.com>
Diffstat (limited to 'src')
-rw-r--r--src/core/SkMask.cpp80
-rw-r--r--src/core/SkMask.h6
2 files changed, 77 insertions, 9 deletions
diff --git a/src/core/SkMask.cpp b/src/core/SkMask.cpp
index ea196f9e45..4e8ad29504 100644
--- a/src/core/SkMask.cpp
+++ b/src/core/SkMask.cpp
@@ -12,24 +12,86 @@
/** returns the product if it is positive and fits in 31 bits. Otherwise this
returns 0.
*/
-static int32_t safeMul32(int32_t a, int32_t b) {
- int64_t size = sk_64_mul(a, b);
- if (size > 0 && sk_64_isS32(size)) {
- return sk_64_asS32(size);
+static size_t safe_mul(size_t a, size_t b) {
+ SkSafeMath safe;
+ size_t r = safe.mul(a, b);
+ if (safe) {
+ return r;
}
+
return 0;
}
+static size_t safe_align4(size_t v) {
+ uint64_t adjusted = v + 3;
+ uint64_t possible = adjusted > v ? (adjusted & ~3) : 0;
+ return SkTFitsIn<size_t>(possible) ? possible : 0;
+}
+
size_t SkMask::computeImageSize() const {
- return safeMul32(fBounds.height(), fRowBytes);
+ auto height = fBounds.height();
+ auto safeHeight = SkTo<uint32_t>(height >= 0 ? height : 0);
+ return safe_mul(safeHeight, fRowBytes);
}
size_t SkMask::computeTotalImageSize() const {
- size_t size = this->computeImageSize();
- if (fFormat == SkMask::k3D_Format) {
- size = safeMul32(SkToS32(size), 3);
+ return ComputeImageSize(fFormat, fBounds.width(), fBounds.height());
+}
+
+static size_t bits_to_bytes(size_t bits) {
+ return (bits + 7) >> 3;
+}
+
+size_t SkMask::AlignmentForMask(SkMask::Format format) {
+ switch (format) {
+ case SkMask::kBW_Format:
+ return alignof(uint8_t);
+ case SkMask::kA8_Format:
+ return alignof(uint8_t);
+ case SkMask::k3D_Format:
+ return alignof(uint8_t);
+ case SkMask::kARGB32_Format:
+ return alignof(uint32_t);
+ case SkMask::kLCD16_Format:
+ return alignof(uint16_t);
+ default:
+ SK_ABORT("Unknown mask format.");
+ break;
+ }
+ // Should not reach here.
+ return alignof(uint64_t);
+}
+
+size_t SkMask::ComputeRowBytes(SkMask::Format format, int32_t width) {
+ auto safeWidth = SkTo<uint32_t>(width >= 0 ? width : 0);
+ switch (format) {
+ case SkMask::kBW_Format:
+ // Always safe.
+ return SkTo<size_t>(bits_to_bytes(safeWidth));
+ case SkMask::kA8_Format:
+ return safe_align4(static_cast<size_t>(safeWidth));
+ case SkMask::k3D_Format:
+ return safe_align4(static_cast<size_t>(safeWidth));
+ case SkMask::kARGB32_Format:
+ return safe_mul(safeWidth, sizeof(uint32_t));
+ case SkMask::kLCD16_Format:
+ return safe_align4(safe_mul(safeWidth, sizeof(uint16_t)));
+ default:
+ SK_ABORT("Unknown mask format.");
+ break;
+ }
+ // Should not reach here.
+ return 0;
+}
+
+size_t SkMask::ComputeImageSize(SkMask::Format format, int32_t width, int32_t height) {
+ size_t size = ComputeRowBytes(format, width);
+ if (format == SkMask::k3D_Format) {
+ size = safe_mul(size, 3);
}
- return size;
+ auto safeHeight = SkTo<uint32_t>(height >= 0 ? height : 0);
+ auto result = safe_mul(size, safeHeight);
+ return result;
}
/** We explicitly use this allocator for SkBimap pixels, so that we can
diff --git a/src/core/SkMask.h b/src/core/SkMask.h
index d4c5e3599c..c3150c895c 100644
--- a/src/core/SkMask.h
+++ b/src/core/SkMask.h
@@ -118,6 +118,12 @@ struct SkMask {
kUninit_Alloc,
kZeroInit_Alloc,
};
+
+ static size_t AlignmentForMask(SkMask::Format format);
+ // Return 0 if overflow.
+ static size_t ComputeRowBytes(SkMask::Format format, int32_t width);
+ // Return 0 if overflow.
+ static size_t ComputeImageSize(SkMask::Format format, int32_t width, int32_t height);
static uint8_t* AllocImage(size_t bytes, AllocType = kUninit_Alloc);
static void FreeImage(void* image);