aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/SkUtils.cpp
diff options
context:
space:
mode:
authorGravatar Hal Canary <halcanary@google.com>2018-06-19 09:53:26 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-06-19 20:11:33 +0000
commitc9b6dda8042dcdd478a3218474fcd1656bb87076 (patch)
treed94bef982979972b2675c06e8d6ffaebb57c7f5c /src/core/SkUtils.cpp
parent3425e22b9e9781570db306dfa70a47e34824be9e (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.cpp52
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;
}