diff options
author | Mike Reed <reed@google.com> | 2017-12-21 13:34:24 -0500 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-12-21 21:06:44 +0000 |
commit | 889d521d8715f4934accb630097bc09bf7ad1a32 (patch) | |
tree | 6e41a72f078156cf8e5338ebd5165df191ab97fd /src/core/SkUtils.cpp | |
parent | 8957a1058e3937bc22192837d2fe87c4a8a047b7 (diff) |
validate text during deserialization
Bug: 796473
Change-Id: I7b6a6c698a5b53c915ef6564852fa51ce7410a3e
Reviewed-on: https://skia-review.googlesource.com/88520
Commit-Queue: Mike Reed <reed@google.com>
Reviewed-by: Hal Canary <halcanary@google.com>
Diffstat (limited to 'src/core/SkUtils.cpp')
-rw-r--r-- | src/core/SkUtils.cpp | 51 |
1 files changed, 43 insertions, 8 deletions
diff --git a/src/core/SkUtils.cpp b/src/core/SkUtils.cpp index 1eb2a7df43..6eceef52c1 100644 --- a/src/core/SkUtils.cpp +++ b/src/core/SkUtils.cpp @@ -82,8 +82,12 @@ int SkUTF8_CountUnichars(const char utf8[]) { } // SAFE: returns -1 if invalid UTF-8 -int SkUTF8_CountUnicharsWithError(const char utf8[], size_t byteLength) { - SkASSERT(utf8 || 0 == byteLength); +int SkUTF8_CountUnichars(const void* text, size_t byteLength) { + SkASSERT(text); + const char* utf8 = static_cast<const char*>(text); + if (byteLength == 0) { + return 0; + } int count = 0; const char* stop = utf8 + byteLength; @@ -91,8 +95,8 @@ int SkUTF8_CountUnicharsWithError(const char utf8[], size_t byteLength) { while (utf8 < stop) { int type = utf8_byte_type(*(const uint8_t*)utf8); SkASSERT(type >= -1 && type <= 4); - if (!utf8_type_is_valid_leading_byte(type) || - utf8 + type > stop) { // Sequence extends beyond end. + if (!utf8_type_is_valid_leading_byte(type) || utf8 + type > stop) { + // Sequence extends beyond end. return -1; } while(type-- > 1) { @@ -254,16 +258,26 @@ int SkUTF16_CountUnichars(const uint16_t src[]) { return count; } -int SkUTF16_CountUnichars(const uint16_t src[], int numberOf16BitValues) { - SkASSERT(src); +// returns -1 on error +int SkUTF16_CountUnichars(const void* text, size_t byteLength) { + SkASSERT(text); + if (byteLength == 0) { + return 0; + } + if (!SkIsAlign2(intptr_t(text)) || !SkIsAlign2(byteLength)) { + return -1; + } - const uint16_t* stop = src + numberOf16BitValues; + const uint16_t* src = static_cast<const uint16_t*>(text); + const uint16_t* stop = src + (byteLength >> 1); int count = 0; while (src < stop) { unsigned c = *src++; SkASSERT(!SkUTF16_IsLowSurrogate(c)); if (SkUTF16_IsHighSurrogate(c)) { - SkASSERT(src < stop); + if (src >= stop) { + return -1; + } c = *src++; SkASSERT(SkUTF16_IsLowSurrogate(c)); } @@ -361,3 +375,24 @@ const char SkHexadecimalDigits::gUpper[16] = const char SkHexadecimalDigits::gLower[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + +// returns -1 on error +int SkUTF32_CountUnichars(const void* text, size_t byteLength) { + if (byteLength == 0) { + return 0; + } + if (!SkIsAlign4(intptr_t(text)) || !SkIsAlign4(byteLength)) { + return -1; + } + const uint32_t kInvalidUnicharMask = 0xFF000000; // unichar fits in 24 bits + const uint32_t* ptr = static_cast<const uint32_t*>(text); + const uint32_t* stop = ptr + (byteLength >> 2); + while (ptr < stop) { + if (*ptr & kInvalidUnicharMask) { + return -1; + } + ptr += 1; + } + return SkToInt(byteLength >> 2); +} + |