diff options
author | Hal Canary <halcanary@google.com> | 2018-06-19 09:53:26 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-06-19 20:11:33 +0000 |
commit | c9b6dda8042dcdd478a3218474fcd1656bb87076 (patch) | |
tree | d94bef982979972b2675c06e8d6ffaebb57c7f5c /src/core/SkUtils.cpp | |
parent | 3425e22b9e9781570db306dfa70a47e34824be9e (diff) |
SkUtils: safe SkUTF16_NextUnichar
Change-Id: Ief70f3055d9612c8934ede967c1048dd7fcb102a
Reviewed-on: https://skia-review.googlesource.com/135705
Commit-Queue: Hal Canary <halcanary@google.com>
Auto-Submit: Hal Canary <halcanary@google.com>
Reviewed-by: Herb Derby <herb@google.com>
Diffstat (limited to 'src/core/SkUtils.cpp')
-rw-r--r-- | src/core/SkUtils.cpp | 52 |
1 files changed, 41 insertions, 11 deletions
diff --git a/src/core/SkUtils.cpp b/src/core/SkUtils.cpp index e6fafa0b07..c12bac50ff 100644 --- a/src/core/SkUtils.cpp +++ b/src/core/SkUtils.cpp @@ -289,22 +289,52 @@ int SkUTF16_CountUnichars(const void* text, size_t byteLength) { return count; } -SkUnichar SkUTF16_NextUnichar(const uint16_t** srcPtr) { - SkASSERT(srcPtr && *srcPtr); - +SkUnichar SkUTF16_NextUnichar(const uint16_t** srcPtr, const uint16_t* endPtr) { + if (!srcPtr || !endPtr) { + return -1; + } const uint16_t* src = *srcPtr; - SkUnichar c = *src++; + if (src >= endPtr) { + return -1; + } + uint16_t c = *src++; + SkUnichar result = c; - SkASSERT(!SkUTF16_IsLowSurrogate(c)); + if (SkUTF16_IsLowSurrogate(c)) { + return -1; // srcPtr should never point at low surrogate. + } if (SkUTF16_IsHighSurrogate(c)) { - unsigned c2 = *src++; - SkASSERT(SkUTF16_IsLowSurrogate(c2)); - - // c = ((c & 0x3FF) << 10) + (c2 & 0x3FF) + 0x10000 - // c = (((c & 0x3FF) + 64) << 10) + (c2 & 0x3FF) - c = (c << 10) + c2 + (0x10000 - (0xD800 << 10) - 0xDC00); + if (src == endPtr) { + return -1; // Truncated string. + } + uint16_t low = *src++; + if (!SkUTF16_IsLowSurrogate(low)) { + return -1; + } + /* + [paraphrased from wikipedia] + Take the high surrogate and subtract 0xD800, then multiply by 0x400. + Take the low surrogate and subtract 0xDC00. Add these two results + together, and finally add 0x10000 to get the final decoded codepoint. + + unicode = (high - 0xD800) * 0x400 + low - 0xDC00 + 0x10000 + unicode = (high * 0x400) - (0xD800 * 0x400) + low - 0xDC00 + 0x10000 + unicode = (high << 10) - (0xD800 << 10) + low - 0xDC00 + 0x10000 + unicode = (high << 10) + low - ((0xD800 << 10) + 0xDC00 - 0x10000) + */ + result = (result << 10) + (SkUnichar)low - ((0xD800 << 10) + 0xDC00 - 0x10000); } *srcPtr = src; + return result; +} + +SkUnichar SkUTF16_NextUnichar(const uint16_t** srcPtr) { + SkUnichar c = SkUTF16_NextUnichar(srcPtr, *srcPtr + 2); + if (c == -1) { + SkASSERT(false); + ++(*srcPtr); + return 0xFFFD; // REPLACEMENT CHARACTER. + } return c; } |