SkUtils:  remove some versions of UTF routines.

Change-Id: Ib1f776ae472117c23d2145253adf25fceb412b32
Reviewed-on: https://skia-review.googlesource.com/143111
Reviewed-by: Herb Derby <herb@google.com>
Commit-Queue: Hal Canary <halcanary@google.com>
diff --git a/gm/atlastext.cpp b/gm/atlastext.cpp
index c30a675..859b4c3 100644
--- a/gm/atlastext.cpp
+++ b/gm/atlastext.cpp
@@ -30,7 +30,7 @@
         return x;
     }
     auto font = SkAtlasTextFont::Make(typeface, size);
-    int cnt = SkUTF8_CountUnichars(text.c_str());
+    int cnt = SkUTF8_CountUnichars(text.c_str(), text.size());
     std::unique_ptr<SkGlyphID[]> glyphs(new SkGlyphID[cnt]);
     typeface->charsToGlyphs(text.c_str(), SkTypeface::Encoding::kUTF8_Encoding, glyphs.get(), cnt);
 
diff --git a/gm/coloremoji_blendmodes.cpp b/gm/coloremoji_blendmodes.cpp
index 1e1608d..8725274 100644
--- a/gm/coloremoji_blendmodes.cpp
+++ b/gm/coloremoji_blendmodes.cpp
@@ -148,7 +148,7 @@
                 textP.setBlendMode(gModes[i]);
                 textP.setTextEncoding(SkPaint::kUTF32_TextEncoding);
                 const char* text = sk_tool_utils::emoji_sample_text();
-                SkUnichar unichar = SkUTF8_ToUnichar(text);
+                SkUnichar unichar = SkUTF8_NextUnichar(&text, text + strlen(text));
                 canvas->drawText(&unichar, 4, x+ w/10.f, y + 7.f*h/8.f, textP);
             }
 #if 1
diff --git a/include/core/SkPaint.h b/include/core/SkPaint.h
index 0664cdd..d7ec9bb 100644
--- a/include/core/SkPaint.h
+++ b/include/core/SkPaint.h
@@ -1455,7 +1455,7 @@
                                       Style style) const;
 
 private:
-    typedef const SkGlyph& (*GlyphCacheProc)(SkGlyphCache*, const char**);
+    typedef const SkGlyph& (*GlyphCacheProc)(SkGlyphCache*, const char**, const char*);
 
     sk_sp<SkTypeface>     fTypeface;
     sk_sp<SkPathEffect>   fPathEffect;
diff --git a/modules/skshaper/src/SkShaper_harfbuzz.cpp b/modules/skshaper/src/SkShaper_harfbuzz.cpp
index 94c899d..2077ded 100644
--- a/modules/skshaper/src/SkShaper_harfbuzz.cpp
+++ b/modules/skshaper/src/SkShaper_harfbuzz.cpp
@@ -124,12 +124,13 @@
             return ret;
         }
 
-        ret.init(utf8, std::move(bidi));
+        ret.init(utf8, utf8 + utf8Bytes, std::move(bidi));
         return ret;
     }
-    BiDiRunIterator(const char* utf8, ICUBiDi bidi)
+    BiDiRunIterator(const char* utf8, const char* end, ICUBiDi bidi)
         : fBidi(std::move(bidi))
         , fEndOfCurrentRun(utf8)
+        , fEndOfAllRuns(end)
         , fUTF16LogicalPosition(0)
         , fLevel(UBIDI_DEFAULT_LTR)
     {}
@@ -137,7 +138,7 @@
         SkASSERT(fUTF16LogicalPosition < ubidi_getLength(fBidi.get()));
         int32_t endPosition = ubidi_getLength(fBidi.get());
         fLevel = ubidi_getLevelAt(fBidi.get(), fUTF16LogicalPosition);
-        SkUnichar u = SkUTF8_NextUnichar(&fEndOfCurrentRun);
+        SkUnichar u = SkUTF8_NextUnichar(&fEndOfCurrentRun, fEndOfAllRuns);
         fUTF16LogicalPosition += SkUTF16_FromUnichar(u);
         UBiDiLevel level;
         while (fUTF16LogicalPosition < endPosition) {
@@ -145,7 +146,7 @@
             if (level != fLevel) {
                 break;
             }
-            u = SkUTF8_NextUnichar(&fEndOfCurrentRun);
+            u = SkUTF8_NextUnichar(&fEndOfCurrentRun, fEndOfAllRuns);
             fUTF16LogicalPosition += SkUTF16_FromUnichar(u);
         }
     }
@@ -162,6 +163,7 @@
 private:
     ICUBiDi fBidi;
     const char* fEndOfCurrentRun;
+    const char* fEndOfAllRuns;
     int32_t fUTF16LogicalPosition;
     UBiDiLevel fLevel;
 };
@@ -182,11 +184,11 @@
     {}
     void consume() override {
         SkASSERT(fCurrent < fEnd);
-        SkUnichar u = SkUTF8_NextUnichar(&fCurrent);
+        SkUnichar u = SkUTF8_NextUnichar(&fCurrent, fEnd);
         fCurrentScript = hb_unicode_script(fHBUnicode, u);
         while (fCurrent < fEnd) {
             const char* prev = fCurrent;
-            u = SkUTF8_NextUnichar(&fCurrent);
+            u = SkUTF8_NextUnichar(&fCurrent, fEnd);
             const hb_script_t script = hb_unicode_script(fHBUnicode, u);
             if (script != fCurrentScript) {
                 if (fCurrentScript == HB_SCRIPT_INHERITED || fCurrentScript == HB_SCRIPT_COMMON) {
@@ -241,7 +243,7 @@
     {}
     void consume() override {
         SkASSERT(fCurrent < fEnd);
-        SkUnichar u = SkUTF8_NextUnichar(&fCurrent);
+        SkUnichar u = SkUTF8_NextUnichar(&fCurrent, fEnd);
         // If the starting typeface can handle this character, use it.
         if (fTypeface->charsToGlyphs(&u, SkTypeface::kUTF32_Encoding, nullptr, 1)) {
             fFallbackTypeface.reset();
@@ -263,7 +265,7 @@
 
         while (fCurrent < fEnd) {
             const char* prev = fCurrent;
-            u = SkUTF8_NextUnichar(&fCurrent);
+            u = SkUTF8_NextUnichar(&fCurrent, fEnd);
 
             // If using a fallback and the initial typeface has this character, stop fallback.
             if (fFallbackTypeface &&
@@ -552,7 +554,7 @@
         const char* utf8Current = utf8Start;
         while (utf8Current < utf8End) {
             unsigned int cluster = utf8Current - utf8Start;
-            hb_codepoint_t u = SkUTF8_NextUnichar(&utf8Current);
+            hb_codepoint_t u = SkUTF8_NextUnichar(&utf8Current, utf8End);
             hb_buffer_add(buffer, u, cluster);
         }
 
diff --git a/src/core/SkDraw.cpp b/src/core/SkDraw.cpp
index 4c9dddf..8a49abf 100644
--- a/src/core/SkDraw.cpp
+++ b/src/core/SkDraw.cpp
@@ -1551,7 +1551,7 @@
     paint.setPathEffect(origPaint.refPathEffect());
 
     while (text < stop) {
-        const SkGlyph& glyph = glyphCacheProc(cache.get(), &text);
+        const SkGlyph& glyph = glyphCacheProc(cache.get(), &text, stop);
         if (glyph.fWidth) {
             const SkPath* path = cache->findPath(glyph);
             if (path) {
diff --git a/src/core/SkFindAndPlaceGlyph.h b/src/core/SkFindAndPlaceGlyph.h
index ae98faa..f602e8d 100644
--- a/src/core/SkFindAndPlaceGlyph.h
+++ b/src/core/SkFindAndPlaceGlyph.h
@@ -115,8 +115,9 @@
     class GlyphFinderInterface {
     public:
         virtual ~GlyphFinderInterface() {}
-        virtual const SkGlyph& lookupGlyph(const char** text) = 0;
-        virtual const SkGlyph& lookupGlyphXY(const char** text, SkFixed x, SkFixed y) = 0;
+        virtual const SkGlyph& lookupGlyph(const char** text, const char* stop) = 0;
+        virtual const SkGlyph& lookupGlyphXY(const char** text, const char* stop,
+                                             SkFixed x, SkFixed y) = 0;
     };
 
     class UtfNGlyphFinder : public GlyphFinderInterface {
@@ -126,17 +127,17 @@
             SkASSERT(cache != nullptr);
         }
 
-        const SkGlyph& lookupGlyph(const char** text) override {
+        const SkGlyph& lookupGlyph(const char** text, const char* stop) override {
             SkASSERT(text != nullptr);
-            return fCache->getUnicharMetrics(nextUnichar(text));
+            return fCache->getUnicharMetrics(nextUnichar(text, stop));
         }
-        const SkGlyph& lookupGlyphXY(const char** text, SkFixed x, SkFixed y) override {
+        const SkGlyph& lookupGlyphXY(const char** text, const char* stop, SkFixed x, SkFixed y) override {
             SkASSERT(text != nullptr);
-            return fCache->getUnicharMetrics(nextUnichar(text), x, y);
+            return fCache->getUnicharMetrics(nextUnichar(text, stop), x, y);
         }
 
     private:
-        virtual SkUnichar nextUnichar(const char** text) = 0;
+        virtual SkUnichar nextUnichar(const char** text, const char* stop) = 0;
         SkGlyphCache* fCache;
     };
 
@@ -145,7 +146,9 @@
         explicit Utf8GlyphFinder(SkGlyphCache* cache) : UtfNGlyphFinder(cache) { }
 
     private:
-        SkUnichar nextUnichar(const char** text) override { return SkUTF8_NextUnichar(text); }
+        SkUnichar nextUnichar(const char** text, const char* stop) override {
+            return SkUTF8_NextUnichar(text, stop);
+        }
     };
 
     class Utf16GlyphFinder final : public UtfNGlyphFinder {
@@ -153,8 +156,8 @@
         explicit Utf16GlyphFinder(SkGlyphCache* cache) : UtfNGlyphFinder(cache) { }
 
     private:
-        SkUnichar nextUnichar(const char** text) override {
-            return SkUTF16_NextUnichar((const uint16_t**)text);
+        SkUnichar nextUnichar(const char** text, const char* stop) override {
+            return SkUTF16_NextUnichar((const uint16_t**)text, (const uint16_t*)stop);
         }
     };
 
@@ -163,7 +166,7 @@
         explicit Utf32GlyphFinder(SkGlyphCache* cache) : UtfNGlyphFinder(cache) { }
 
     private:
-        SkUnichar nextUnichar(const char** text) override {
+        SkUnichar nextUnichar(const char** text, const char* stop) override {
             const int32_t* ptr = *(const int32_t**)text;
             SkUnichar uni = *ptr++;
             *text = (const char*)ptr;
@@ -178,10 +181,11 @@
             SkASSERT(cache != nullptr);
         }
 
-        const SkGlyph& lookupGlyph(const char** text) override {
+        const SkGlyph& lookupGlyph(const char** text, const char*) override {
             return fCache->getGlyphIDMetrics(nextGlyphId(text));
         }
-        const SkGlyph& lookupGlyphXY(const char** text, SkFixed x, SkFixed y) override {
+        const SkGlyph& lookupGlyphXY(const char** text, const char*,
+                                     SkFixed x, SkFixed y) override {
             return fCache->getGlyphIDMetrics(nextGlyphId(text), x, y);
         }
 
@@ -319,7 +323,8 @@
         // compile error.
         // See GCC bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60277
         virtual SkPoint findAndPositionGlyph(
-            const char** text, SkPoint position, ProcessOneGlyph&& processOneGlyph) {
+            const char** text, const char* stop, SkPoint position,
+            ProcessOneGlyph&& processOneGlyph) {
             SK_ABORT("Should never get here.");
             return {0.0f, 0.0f};
         }
@@ -335,12 +340,13 @@
             : fGlyphFinder(glyphFinder) { }
 
         SkPoint findAndPositionGlyph(
-            const char** text, SkPoint position, ProcessOneGlyph&& processOneGlyph) override {
+            const char** text, const char* stop, SkPoint position,
+            ProcessOneGlyph&& processOneGlyph) override {
 
             // Find the glyph.
             SkIPoint lookupPosition = SubpixelAlignment(kAxisAlignment, position);
             const SkGlyph& renderGlyph =
-                fGlyphFinder->lookupGlyphXY(text, lookupPosition.fX, lookupPosition.fY);
+                fGlyphFinder->lookupGlyphXY(text, stop, lookupPosition.fX, lookupPosition.fY);
 
             // If the glyph has no width (no pixels) then don't bother processing it.
             if (renderGlyph.fWidth > 0) {
@@ -365,9 +371,10 @@
         }
 
         SkPoint findAndPositionGlyph(
-            const char** text, SkPoint position, ProcessOneGlyph&& processOneGlyph) override {
+            const char** text, const char* stop, SkPoint position,
+            ProcessOneGlyph&& processOneGlyph) override {
             SkPoint finalPosition = position;
-            const SkGlyph& glyph = fGlyphFinder->lookupGlyph(text);
+            const SkGlyph& glyph = fGlyphFinder->lookupGlyph(text, stop);
 
             if (glyph.fWidth > 0) {
                 processOneGlyph(glyph, finalPosition, {SK_ScalarHalf, SK_ScalarHalf});
@@ -407,7 +414,7 @@
         while (text < stop) {
             // don't need x, y here, since all subpixel variants will have the
             // same advance
-            const SkGlyph& glyph = glyphFinder->lookupGlyph(&text);
+            const SkGlyph& glyph = glyphFinder->lookupGlyph(&text, stop);
 
             x += SkFloatToScalar(glyph.fAdvanceX);
             y += SkFloatToScalar(glyph.fAdvanceY);
@@ -451,7 +458,7 @@
         while (cursor < stop) {
             SkPoint mappedPoint = mapper.TranslationMapper::map(positions->nextPoint());
             positioner.Positioner::findAndPositionGlyph(
-                &cursor, mappedPoint, std::forward<ProcessOneGlyph>(processOneGlyph));
+                &cursor, stop, mappedPoint, std::forward<ProcessOneGlyph>(processOneGlyph));
         }
         return;
     }
@@ -479,7 +486,7 @@
     while (text < stop) {
         SkPoint mappedPoint = mapper->map(positionReader->nextPoint());
         findAndPosition->findAndPositionGlyph(
-            &text, mappedPoint, std::forward<ProcessOneGlyph>(processOneGlyph));
+            &text, stop, mappedPoint, std::forward<ProcessOneGlyph>(processOneGlyph));
     }
 }
 
diff --git a/src/core/SkOverdrawCanvas.cpp b/src/core/SkOverdrawCanvas.cpp
index e8327e5..35656e0 100644
--- a/src/core/SkOverdrawCanvas.cpp
+++ b/src/core/SkOverdrawCanvas.cpp
@@ -95,22 +95,26 @@
     return;
 }
 
-typedef int (*CountTextProc)(const char* text);
-static int count_utf16(const char* text) {
-    const uint16_t* prev = (uint16_t*)text;
-    (void)SkUTF16_NextUnichar(&prev);
+typedef int (*CountTextProc)(const char* text, const char* stop);
+static int count_utf16(const char* text, const char* stop) {
+    const uint16_t* prev = (const uint16_t*)text;
+    (void)SkUTF16_NextUnichar(&prev, (const uint16_t*)stop);
     return SkToInt((const char*)prev - text);
 }
-static int return_4(const char* text) { return 4; }
-static int return_2(const char* text) { return 2; }
+static int return_4(const char* text, const char* stop) { return 4; }
+static int return_2(const char* text, const char* stop) { return 2; }
+static int count_utf8(const char* text, const char* stop) {
+    return SkUTF8_LeadByteToCount(*(const uint8_t*)text);
+}
 
 void SkOverdrawCanvas::onDrawTextRSXform(const void* text, size_t byteLength,
                                          const SkRSXform xform[], const SkRect*,
                                          const SkPaint& paint) {
+    const char* stop = (const char*)text + byteLength;
     CountTextProc proc = nullptr;
     switch (paint.getTextEncoding()) {
         case SkPaint::kUTF8_TextEncoding:
-            proc = SkUTF8_CountUTF8Bytes;
+            proc = count_utf8;
             break;
         case SkPaint::kUTF16_TextEncoding:
             proc = count_utf16;
@@ -129,7 +133,8 @@
     while ((const char*)text < (const char*)stopText) {
         matrix.setRSXform(*xform++);
         matrix.setConcat(this->getTotalMatrix(), matrix);
-        int subLen = proc((const char*)text);
+        int subLen = proc((const char*)text, stop);
+        SkASSERT(subLen > 0);
 
         this->save();
         this->concat(matrix);
diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp
index 7643bab..0fdf58b 100644
--- a/src/core/SkPaint.cpp
+++ b/src/core/SkPaint.cpp
@@ -449,7 +449,7 @@
             const uint16_t* text16 = (const uint16_t*)text;
             const uint16_t* stop16 = (const uint16_t*)stop;
             while (text16 < stop16) {
-                *gptr++ = cache->unicharToGlyph(SkUTF16_NextUnichar(&text16));
+                *gptr++ = cache->unicharToGlyph(SkUTF16_NextUnichar(&text16, stop16));
             }
             break;
         }
@@ -493,7 +493,7 @@
             const char* text = static_cast<const char*>(textData);
             const char* stop = text + byteLength;
             while (text < stop) {
-                if (0 == cache->unicharToGlyph(SkUTF8_NextUnichar(&text))) {
+                if (0 == cache->unicharToGlyph(SkUTF8_NextUnichar(&text, stop))) {
                     return false;
                 }
             }
@@ -503,7 +503,7 @@
             const uint16_t* text = static_cast<const uint16_t*>(textData);
             const uint16_t* stop = text + (byteLength >> 1);
             while (text < stop) {
-                if (0 == cache->unicharToGlyph(SkUTF16_NextUnichar(&text))) {
+                if (0 == cache->unicharToGlyph(SkUTF16_NextUnichar(&text, stop))) {
                     return false;
                 }
             }
@@ -546,23 +546,27 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 static const SkGlyph& sk_getMetrics_utf8_next(SkGlyphCache* cache,
-                                              const char** text) {
+                                              const char** text,
+                                              const char* stop) {
     SkASSERT(cache != nullptr);
     SkASSERT(text != nullptr);
 
-    return cache->getUnicharMetrics(SkUTF8_NextUnichar(text));
+    return cache->getUnicharMetrics(SkUTF8_NextUnichar(text, stop));
 }
 
 static const SkGlyph& sk_getMetrics_utf16_next(SkGlyphCache* cache,
-                                               const char** text) {
+                                               const char** text,
+                                               const char* stop) {
     SkASSERT(cache != nullptr);
     SkASSERT(text != nullptr);
 
-    return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text));
+    return cache->getUnicharMetrics(
+            SkUTF16_NextUnichar((const uint16_t**)text, (const uint16_t*)stop));
 }
 
 static const SkGlyph& sk_getMetrics_utf32_next(SkGlyphCache* cache,
-                                               const char** text) {
+                                               const char** text,
+                                               const char* stop) {
     SkASSERT(cache != nullptr);
     SkASSERT(text != nullptr);
 
@@ -573,7 +577,8 @@
 }
 
 static const SkGlyph& sk_getMetrics_glyph_next(SkGlyphCache* cache,
-                                               const char** text) {
+                                               const char** text,
+                                               const char* stop) {
     SkASSERT(cache != nullptr);
     SkASSERT(text != nullptr);
 
@@ -585,23 +590,27 @@
 }
 
 static const SkGlyph& sk_getAdvance_utf8_next(SkGlyphCache* cache,
-                                              const char** text) {
+                                              const char** text,
+                                              const char* stop) {
     SkASSERT(cache != nullptr);
     SkASSERT(text != nullptr);
 
-    return cache->getUnicharAdvance(SkUTF8_NextUnichar(text));
+    return cache->getUnicharAdvance(SkUTF8_NextUnichar(text, stop));
 }
 
 static const SkGlyph& sk_getAdvance_utf16_next(SkGlyphCache* cache,
-                                               const char** text) {
+                                               const char** text,
+                                               const char* stop) {
     SkASSERT(cache != nullptr);
     SkASSERT(text != nullptr);
 
-    return cache->getUnicharAdvance(SkUTF16_NextUnichar((const uint16_t**)text));
+    return cache->getUnicharAdvance(
+            SkUTF16_NextUnichar((const uint16_t**)text, (const uint16_t*)stop));
 }
 
 static const SkGlyph& sk_getAdvance_utf32_next(SkGlyphCache* cache,
-                                               const char** text) {
+                                               const char** text,
+                                               const char* stop) {
     SkASSERT(cache != nullptr);
     SkASSERT(text != nullptr);
 
@@ -612,7 +621,8 @@
 }
 
 static const SkGlyph& sk_getAdvance_glyph_next(SkGlyphCache* cache,
-                                               const char** text) {
+                                               const char** text,
+                                               const char* stop) {
     SkASSERT(cache != nullptr);
     SkASSERT(text != nullptr);
 
@@ -750,18 +760,18 @@
 
     int         n = 1;
     const char* stop = (const char*)text + byteLength;
-    const SkGlyph* g = &glyphCacheProc(cache, &text);
+    const SkGlyph* g = &glyphCacheProc(cache, &text, stop);
     SkScalar x = advance(*g, xyIndex);
 
     if (nullptr == bounds) {
         for (; text < stop; n++) {
-            x += advance(glyphCacheProc(cache, &text), xyIndex);
+            x += advance(glyphCacheProc(cache, &text, stop), xyIndex);
         }
     } else {
         set_bounds(*g, bounds);
 
         for (; text < stop; n++) {
-            g = &glyphCacheProc(cache, &text);
+            g = &glyphCacheProc(cache, &text, stop);
             joinBoundsProc(*g, bounds, x);
             x += advance(*g, xyIndex);
         }
@@ -842,7 +852,7 @@
 
     while (text < stop) {
         const char* curr = text;
-        SkScalar x = advance(glyphCacheProc(cache.get(), &text), xyIndex);
+        SkScalar x = advance(glyphCacheProc(cache.get(), &text, stop), xyIndex);
         if ((width += x) > maxWidth) {
             width -= x;
             text = curr;
@@ -933,7 +943,7 @@
 
     if (scale) {
         while (text < stop) {
-            const SkGlyph& g = glyphCacheProc(cache.get(), &text);
+            const SkGlyph& g = glyphCacheProc(cache.get(), &text, stop);
             if (widths) {
                 *widths++ = advance(g, xyIndex) * scale;
             }
@@ -944,7 +954,7 @@
         }
     } else {
         while (text < stop) {
-            const SkGlyph& g = glyphCacheProc(cache.get(), &text);
+            const SkGlyph& g = glyphCacheProc(cache.get(), &text, stop);
             if (widths) {
                 *widths++ = advance(g, xyIndex);
             }
@@ -1464,7 +1474,7 @@
 
 bool SkTextToPathIter::next(const SkPath** path, SkScalar* xpos) {
     if (fText < fStop) {
-        const SkGlyph& glyph = fGlyphCacheProc(fCache.get(), &fText);
+        const SkGlyph& glyph = fGlyphCacheProc(fCache.get(), &fText, fStop);
 
         fXPos += fPrevAdvance * fScale;
         fPrevAdvance = advance(glyph, fXYIndex);   // + fPaint.getTextTracking();
@@ -1487,7 +1497,7 @@
 }
 
 bool SkTextInterceptsIter::next(SkScalar* array, int* count) {
-    const SkGlyph& glyph = fGlyphCacheProc(fCache.get(), &fText);
+    const SkGlyph& glyph = fGlyphCacheProc(fCache.get(), &fText, fStop);
     fXPos += fPrevAdvance * fScale;
     fPrevAdvance = advance(glyph, fXYIndex);   // + fPaint.getTextTracking();
     if (fCache->findPath(glyph)) {
diff --git a/src/core/SkStringUtils.cpp b/src/core/SkStringUtils.cpp
index c4c1739..5004785 100644
--- a/src/core/SkStringUtils.cpp
+++ b/src/core/SkStringUtils.cpp
@@ -55,13 +55,14 @@
 
 SkString SkStringFromUTF16(const uint16_t* src, size_t count) {
     SkString ret;
+    const uint16_t* stop = src + count;
     if (count > 0) {
         SkASSERT(src);
         size_t n = 0;
         const uint16_t* end = src + count;
         for (const uint16_t* ptr = src; ptr < end;) {
             const uint16_t* last = ptr;
-            SkUnichar u = SkUTF16_NextUnichar(&ptr);
+            SkUnichar u = SkUTF16_NextUnichar(&ptr, stop);
             size_t s = SkUTF8_FromUnichar(u);
             if (n > UINT32_MAX - s) {
                 end = last;  // truncate input string
@@ -72,7 +73,7 @@
         ret = SkString(n);
         char* out = ret.writable_str();
         for (const uint16_t* ptr = src; ptr < end;) {
-            out += SkUTF8_FromUnichar(SkUTF16_NextUnichar(&ptr), out);
+            out += SkUTF8_FromUnichar(SkUTF16_NextUnichar(&ptr, stop), out);
         }
         SkASSERT(out == ret.writable_str() + n);
     }
diff --git a/src/core/SkTextToPathIter.h b/src/core/SkTextToPathIter.h
index c135de6..875cf5a 100644
--- a/src/core/SkTextToPathIter.h
+++ b/src/core/SkTextToPathIter.h
@@ -71,7 +71,7 @@
         if (TextType::kPosText == fTextType
                 && fPaint.getTextAlign() != SkPaint::kLeft_Align) { // need to measure first
             const char* text = fText;
-            const SkGlyph& glyph = fGlyphCacheProc(fCache.get(), &text);
+            const SkGlyph& glyph = fGlyphCacheProc(fCache.get(), &text, fStop);
             SkScalar width = (&glyph.fAdvanceX)[0] * fScale;
             if (fPaint.getTextAlign() == SkPaint::kCenter_Align) {
                 width = SkScalarHalf(width);
diff --git a/src/gpu/text/GrTextContext.cpp b/src/gpu/text/GrTextContext.cpp
index e68be09..6a34895 100644
--- a/src/gpu/text/GrTextContext.cpp
+++ b/src/gpu/text/GrTextContext.cpp
@@ -339,7 +339,7 @@
     SkTextMapStateProc tmsProc(SkMatrix::I(), offset, scalarsPerPosition);
 
     while (text < stop) {
-        const SkGlyph& glyph = glyphCacheProc(cache.get(), &text);
+        const SkGlyph& glyph = glyphCacheProc(cache.get(), &text, stop);
         if (glyph.fWidth) {
             SkPoint loc;
             tmsProc(pos, &loc);
@@ -554,7 +554,7 @@
         while (text < stop) {
             const char* lastText = text;
             // the last 2 parameters are ignored
-            const SkGlyph& glyph = glyphCacheProc(cache.get(), &text);
+            const SkGlyph& glyph = glyphCacheProc(cache.get(), &text, stop);
 
             if (glyph.fWidth) {
                 SkPoint glyphPos(offset);
@@ -664,7 +664,7 @@
         const char* stop = text + fFallbackTxt.count();
         SkPoint* glyphPos = fFallbackPos.begin();
         while (text < stop) {
-            const SkGlyph& glyph = glyphCacheProc(cache.get(), &text);
+            const SkGlyph& glyph = glyphCacheProc(cache.get(), &text, stop);
             if (!fUseTransformedFallback) {
                 fViewMatrix.mapPoints(glyphPos, 1);
                 glyphPos->fX = SkScalarFloorToScalar(glyphPos->fX);
diff --git a/src/gpu/text/GrTextUtils.cpp b/src/gpu/text/GrTextUtils.cpp
index 6f043e1..ec5389c 100644
--- a/src/gpu/text/GrTextUtils.cpp
+++ b/src/gpu/text/GrTextUtils.cpp
@@ -36,7 +36,7 @@
     SkASSERT(path);
     SkASSERT(xpos);
     if (fText < fStop) {
-        const SkGlyph& glyph = fGlyphCacheProc(fCache.get(), &fText);
+        const SkGlyph& glyph = fGlyphCacheProc(fCache.get(), &fText, fStop);
 
         fXPos += fPrevAdvance * fScale;
         SkASSERT(0 == fXYIndex || 1 == fXYIndex);
diff --git a/src/svg/SkSVGDevice.cpp b/src/svg/SkSVGDevice.cpp
index c2a402f..4a83a9c 100644
--- a/src/svg/SkSVGDevice.cpp
+++ b/src/svg/SkSVGDevice.cpp
@@ -133,6 +133,7 @@
 
         int count = paint.countText(text, byteLen);
 
+        const char* stop = (const char*)text + byteLen;
         switch(paint.getTextEncoding()) {
         case SkPaint::kGlyphID_TextEncoding: {
             SkASSERT(count * sizeof(uint16_t) == byteLen);
@@ -145,14 +146,14 @@
         case SkPaint::kUTF8_TextEncoding: {
             const char* c8 = reinterpret_cast<const char*>(text);
             for (int i = 0; i < count; ++i) {
-                this->appendUnichar(SkUTF8_NextUnichar(&c8));
+                this->appendUnichar(SkUTF8_NextUnichar(&c8, stop));
             }
             SkASSERT(reinterpret_cast<const char*>(text) + byteLen == c8);
         } break;
         case SkPaint::kUTF16_TextEncoding: {
             const uint16_t* c16 = reinterpret_cast<const uint16_t*>(text);
             for (int i = 0; i < count; ++i) {
-                this->appendUnichar(SkUTF16_NextUnichar(&c16));
+                this->appendUnichar(SkUTF16_NextUnichar(&c16, (const uint16_t*)stop));
             }
             SkASSERT(SkIsAlign2(byteLen));
             SkASSERT(reinterpret_cast<const uint16_t*>(text) + (byteLen / 2) == c16);
diff --git a/tests/UtilsTest.cpp b/tests/UtilsTest.cpp
index 7e11f84..6f8ec91 100644
--- a/tests/UtilsTest.cpp
+++ b/tests/UtilsTest.cpp
@@ -177,7 +177,7 @@
         size_t count2 = SkUTF16_CountUnichars(buf, 2 * sizeof(uint16_t));
         REPORTER_ASSERT(reporter, count2 == 1);
         const uint16_t* ptr = buf;
-        SkUnichar c = SkUTF16_NextUnichar(&ptr);
+        SkUnichar c = SkUTF16_NextUnichar(&ptr, buf + SK_ARRAY_COUNT(buf));
         REPORTER_ASSERT(reporter, c == gUni[i]);
         REPORTER_ASSERT(reporter, ptr - buf == 2);
     }
@@ -203,13 +203,12 @@
 
     for (size_t i = 0; i < SK_ARRAY_COUNT(gTest); i++) {
         const char* p = gTest[i].fUtf8;
-        int         n = SkUTF8_CountUnichars(p);
-        SkUnichar   u0 = SkUTF8_ToUnichar(gTest[i].fUtf8);
-        SkUnichar   u1 = SkUTF8_NextUnichar(&p);
+        const char* stop = p + strlen(p);
+        int         n = SkUTF8_CountUnichars(p, strlen(p));
+        SkUnichar   u1 = SkUTF8_NextUnichar(&p, stop);
 
         REPORTER_ASSERT(reporter, n == 1);
-        REPORTER_ASSERT(reporter, u0 == u1);
-        REPORTER_ASSERT(reporter, u0 == gTest[i].fUni);
+        REPORTER_ASSERT(reporter, u1 == gTest[i].fUni);
         REPORTER_ASSERT(reporter,
                         p - gTest[i].fUtf8 == (int)strlen(gTest[i].fUtf8));
     }
diff --git a/tools/fonts/create_test_font.cpp b/tools/fonts/create_test_font.cpp
index 6cbcf6e..36ead3c 100644
--- a/tools/fonts/create_test_font.cpp
+++ b/tools/fonts/create_test_font.cpp
@@ -144,7 +144,7 @@
         char str[1];
         str[0] = ch;
         const char* used = str;
-        SkUnichar index = SkUTF8_NextUnichar(&used);
+        SkUnichar index = SkUTF8_NextUnichar(&used, str + 1);
         SkPath path;
         paint.getTextPath((const void*) &index, 2, 0, 0, &path);
         SkPath::RawIter iter(path);