aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Florin Malita <fmalita@chromium.org>2017-11-22 10:11:12 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-11-22 18:54:14 +0000
commitd923a71a113d97dc87b4424c25d5b5019331db24 (patch)
tree09921f16f2e08faf513fe4ddaed511d6051d9b2e /src
parentd86a4f7c4a8f3cb08c88579f1f0d514a7bfc20af (diff)
Use SkSafeMath for text blob storage calculations
Change-Id: I028895dee81d99b1fa2a9acfa3db3f4bcb0f8f64 Reviewed-on: https://skia-review.googlesource.com/73823 Reviewed-by: Herb Derby <herb@google.com> Commit-Queue: Florin Malita <fmalita@chromium.org>
Diffstat (limited to 'src')
-rw-r--r--src/core/SkSafeMath.h5
-rw-r--r--src/core/SkTextBlob.cpp89
2 files changed, 67 insertions, 27 deletions
diff --git a/src/core/SkSafeMath.h b/src/core/SkSafeMath.h
index f781c2cf21..1005d069a8 100644
--- a/src/core/SkSafeMath.h
+++ b/src/core/SkSafeMath.h
@@ -43,6 +43,11 @@ public:
return a + b;
}
+ size_t alignUp(size_t x, size_t alignment) {
+ SkASSERT(alignment && !(alignment & (alignment - 1)));
+ return add(x, alignment - 1) & ~(alignment - 1);
+ }
+
private:
uint32_t mul32(uint32_t x, uint32_t y) {
uint64_t bx = x;
diff --git a/src/core/SkTextBlob.cpp b/src/core/SkTextBlob.cpp
index 839b008738..3879c1e78e 100644
--- a/src/core/SkTextBlob.cpp
+++ b/src/core/SkTextBlob.cpp
@@ -7,10 +7,13 @@
#include "SkTextBlobRunIterator.h"
-#include "SkValidatingReadBuffer.h"
+#include "SkSafeMath.h"
#include "SkTypeface.h"
+#include "SkValidatingReadBuffer.h"
#include "SkWriteBuffer.h"
+#include <limits>
+
#if SK_SUPPORT_GPU
#include "text/GrTextBlobCache.h"
#endif
@@ -187,19 +190,26 @@ public:
: nullptr;
}
- static size_t StorageSize(int glyphCount, int textSize,
- SkTextBlob::GlyphPositioning positioning) {
+ static size_t StorageSize(uint32_t glyphCount, uint32_t textSize,
+ SkTextBlob::GlyphPositioning positioning,
+ SkSafeMath* safe) {
static_assert(SkIsAlign4(sizeof(SkScalar)), "SkScalar size alignment");
+
+ auto glyphSize = safe->mul(glyphCount, sizeof(uint16_t)),
+ posSize = safe->mul(PosCount(glyphCount, positioning, safe), sizeof(SkScalar));
+
// RunRecord object + (aligned) glyph buffer + position buffer
- size_t size = sizeof(SkTextBlob::RunRecord)
- + SkAlign4(glyphCount* sizeof(uint16_t))
- + PosCount(glyphCount, positioning) * sizeof(SkScalar);
- if (textSize > 0) { // Extended run.
- size += sizeof(uint32_t)
- + sizeof(uint32_t) * glyphCount
- + textSize;
+ auto size = sizeof(SkTextBlob::RunRecord);
+ size = safe->add(size, safe->alignUp(glyphSize, 4));
+ size = safe->add(size, posSize);
+
+ if (textSize) { // Extended run.
+ size = safe->add(size, sizeof(uint32_t));
+ size = safe->add(size, safe->mul(glyphCount, sizeof(uint32_t)));
+ size = safe->add(size, textSize);
}
- return SkAlignPtr(size);
+
+ return safe->alignUp(size, sizeof(void*));
}
static const RunRecord* First(const SkTextBlob* blob) {
@@ -238,20 +248,27 @@ private:
};
static const RunRecord* NextUnchecked(const RunRecord* run) {
- return reinterpret_cast<const RunRecord*>(
- reinterpret_cast<const uint8_t*>(run)
- + StorageSize(run->glyphCount(), run->textSize(), run->positioning()));
+ SkSafeMath safe;
+ auto res = reinterpret_cast<const RunRecord*>(
+ reinterpret_cast<const uint8_t*>(run)
+ + StorageSize(run->glyphCount(), run->textSize(), run->positioning(), &safe));
+ SkASSERT(safe);
+ return res;
}
- static size_t PosCount(int glyphCount,
- SkTextBlob::GlyphPositioning positioning) {
- return glyphCount * ScalarsPerGlyph(positioning);
+ static size_t PosCount(uint32_t glyphCount,
+ SkTextBlob::GlyphPositioning positioning,
+ SkSafeMath* safe) {
+ return safe->mul(glyphCount, ScalarsPerGlyph(positioning));
}
uint32_t* textSizePtr() const {
// textSize follows the position buffer.
SkASSERT(isExtended());
- return (uint32_t*)(&this->posBuffer()[PosCount(fCount, positioning())]);
+ SkSafeMath safe;
+ auto res = (uint32_t*)(&this->posBuffer()[PosCount(fCount, positioning(), &safe)]);
+ SkASSERT(safe);
+ return res;
}
void grow(uint32_t count) {
@@ -525,8 +542,10 @@ void SkTextBlobBuilder::updateDeferredBounds() {
}
void SkTextBlobBuilder::reserve(size_t size) {
+ SkSafeMath safe;
+
// We don't currently pre-allocate, but maybe someday...
- if (fStorageUsed + size <= fStorageSize) {
+ if (safe.add(fStorageUsed, size) <= fStorageSize && safe) {
return;
}
@@ -536,16 +555,18 @@ void SkTextBlobBuilder::reserve(size_t size) {
SkASSERT(0 == fStorageUsed);
// the first allocation also includes blob storage
- fStorageUsed += sizeof(SkTextBlob);
+ fStorageUsed = sizeof(SkTextBlob);
}
- fStorageSize = fStorageUsed + size;
+ fStorageSize = safe.add(fStorageUsed, size);
+
// FYI: This relies on everything we store being relocatable, particularly SkPaint.
- fStorage.realloc(fStorageSize);
+ // Also, this is counting on the underlying realloc to throw when passed max().
+ fStorage.realloc(safe ? fStorageSize : std::numeric_limits<size_t>::max());
}
bool SkTextBlobBuilder::mergeRun(const SkPaint &font, SkTextBlob::GlyphPositioning positioning,
- int count, SkPoint offset) {
+ uint32_t count, SkPoint offset) {
if (0 == fLastRun) {
SkASSERT(0 == fRunCount);
return false;
@@ -576,8 +597,14 @@ bool SkTextBlobBuilder::mergeRun(const SkPaint &font, SkTextBlob::GlyphPositioni
return false;
}
- size_t sizeDelta = SkTextBlob::RunRecord::StorageSize(run->glyphCount() + count, 0, positioning) -
- SkTextBlob::RunRecord::StorageSize(run->glyphCount(), 0, positioning);
+ SkSafeMath safe;
+ size_t sizeDelta =
+ SkTextBlob::RunRecord::StorageSize(run->glyphCount() + count, 0, positioning, &safe) -
+ SkTextBlob::RunRecord::StorageSize(run->glyphCount() , 0, positioning, &safe);
+ if (!safe) {
+ return false;
+ }
+
this->reserve(sizeDelta);
// reserve may have realloced
@@ -610,7 +637,13 @@ void SkTextBlobBuilder::allocInternal(const SkPaint &font,
if (textSize != 0 || !this->mergeRun(font, positioning, count, offset)) {
this->updateDeferredBounds();
- size_t runSize = SkTextBlob::RunRecord::StorageSize(count, textSize, positioning);
+ SkSafeMath safe;
+ size_t runSize = SkTextBlob::RunRecord::StorageSize(count, textSize, positioning, &safe);
+ if (!safe) {
+ fCurrentRunBuffer = { nullptr, nullptr, nullptr, nullptr };
+ return;
+ }
+
this->reserve(runSize);
SkASSERT(fStorageUsed >= sizeof(SkTextBlob));
@@ -691,16 +724,18 @@ sk_sp<SkTextBlob> SkTextBlobBuilder::make() {
SkDEBUGCODE(const_cast<SkTextBlob*>(blob)->fStorageSize = fStorageSize;)
SkDEBUGCODE(
+ SkSafeMath safe;
size_t validateSize = sizeof(SkTextBlob);
for (const auto* run = SkTextBlob::RunRecord::First(blob); run;
run = SkTextBlob::RunRecord::Next(run)) {
validateSize += SkTextBlob::RunRecord::StorageSize(
- run->fCount, run->textSize(), run->positioning());
+ run->fCount, run->textSize(), run->positioning(), &safe);
run->validate(reinterpret_cast<const uint8_t*>(blob) + fStorageUsed);
fRunCount--;
}
SkASSERT(validateSize == fStorageUsed);
SkASSERT(fRunCount == 0);
+ SkASSERT(safe);
)
fStorageUsed = 0;