diff options
author | Florin Malita <fmalita@chromium.org> | 2017-11-22 10:11:12 -0500 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-11-22 18:54:14 +0000 |
commit | d923a71a113d97dc87b4424c25d5b5019331db24 (patch) | |
tree | 09921f16f2e08faf513fe4ddaed511d6051d9b2e /src | |
parent | d86a4f7c4a8f3cb08c88579f1f0d514a7bfc20af (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.h | 5 | ||||
-rw-r--r-- | src/core/SkTextBlob.cpp | 89 |
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; |