Backed out changeset 110fbc2ebc1a (bug 1034627)
authorEd Morley <emorley@mozilla.com>
Fri, 11 Jul 2014 15:46:33 +0100
changeset 193599 6904f207728c0a630deffdb16c020d67ba37232d
parent 193598 1166b5c0e91646128201c4491218d81d9efa44f4
child 193600 1e19958b0386d5ebd3d5363d18436c6cea6325b9
push idunknown
push userunknown
push dateunknown
bugs1034627
milestone33.0a1
backs out110fbc2ebc1a74d5aa424c911aebd792550745ce
Backed out changeset 110fbc2ebc1a (bug 1034627)
js/public/CharacterEncoding.h
js/src/vm/CharacterEncoding.cpp
--- a/js/public/CharacterEncoding.h
+++ b/js/public/CharacterEncoding.h
@@ -197,28 +197,14 @@ UTF8CharsToNewTwoByteCharsZ(JSContext *c
 /*
  * The same as UTF8CharsToNewTwoByteCharsZ(), except that any malformed UTF-8 characters
  * will be replaced by \uFFFD. No exception will be thrown for malformed UTF-8
  * input.
  */
 extern TwoByteCharsZ
 LossyUTF8CharsToNewTwoByteCharsZ(JSContext *cx, const UTF8Chars utf8, size_t *outlen);
 
-/*
- * Returns the length of the char buffer required to encode |s| as UTF8.
- * Does not include the null-terminator.
- */
-JS_PUBLIC_API(size_t)
-GetDeflatedUTF8StringLength(JSFlatString *s);
-
-/*
- * Encode |src| as UTF8. The caller must ensure |dst| has enough space.
- * Does not write the null terminator.
- */
-JS_PUBLIC_API(void)
-DeflateStringToUTF8Buffer(JSFlatString *src, mozilla::RangedPtr<char> dst);
-
 } // namespace JS
 
 inline void JS_free(JS::Latin1CharsZ &ptr) { js_free((void*)ptr.get()); }
 inline void JS_free(JS::UTF8CharsZ &ptr) { js_free((void*)ptr.get()); }
 
 #endif /* js_CharacterEncoding_h */
--- a/js/src/vm/CharacterEncoding.cpp
+++ b/js/src/vm/CharacterEncoding.cpp
@@ -60,100 +60,112 @@ GetDeflatedUTF8StringLength(const CharT 
         while (v) {
             v >>= 5;
             nbytes++;
         }
     }
     return nbytes;
 }
 
-JS_PUBLIC_API(size_t)
-JS::GetDeflatedUTF8StringLength(JSFlatString *s)
-{
-    JS::AutoCheckCannotGC nogc;
-    return s->hasLatin1Chars()
-           ? ::GetDeflatedUTF8StringLength(s->latin1Chars(nogc), s->length())
-           : ::GetDeflatedUTF8StringLength(s->twoByteChars(nogc), s->length());
+static bool
+PutUTF8ReplacementCharacter(char **dst, size_t *dstlenp) {
+    if (*dstlenp < 3)
+        return false;
+    *(*dst)++ = (char) 0xEF;
+    *(*dst)++ = (char) 0xBF;
+    *(*dst)++ = (char) 0xBD;
+    *dstlenp -= 3;
+    return true;
 }
 
-static void
-PutUTF8ReplacementCharacter(mozilla::RangedPtr<char> &dst)
+/*
+ * Write up to |*dstlenp| bytes into |dst|.  Writes the number of bytes used
+ * into |*dstlenp| on success.  Returns false on failure.
+ */
+template <typename CharT>
+static bool
+DeflateStringToUTF8Buffer(js::ThreadSafeContext *cx, const CharT *src, size_t srclen,
+                          char *dst, size_t *dstlenp)
 {
-    *dst++ = char(0xEF);
-    *dst++ = char(0xBF);
-    *dst++ = char(0xBD);
-}
+    size_t dstlen = *dstlenp;
+    size_t origDstlen = dstlen;
 
-template <typename CharT>
-static void
-DeflateStringToUTF8Buffer(const CharT *src, size_t srclen, mozilla::RangedPtr<char> dst)
-{
     while (srclen) {
         uint32_t v;
         jschar c = *src++;
         srclen--;
         if (c >= 0xDC00 && c <= 0xDFFF) {
-            PutUTF8ReplacementCharacter(dst);
+            if (!PutUTF8ReplacementCharacter(&dst, &dstlen))
+                goto bufferTooSmall;
             continue;
         } else if (c < 0xD800 || c > 0xDBFF) {
             v = c;
         } else {
             if (srclen < 1) {
-                PutUTF8ReplacementCharacter(dst);
+                if (!PutUTF8ReplacementCharacter(&dst, &dstlen))
+                    goto bufferTooSmall;
                 continue;
             }
             jschar c2 = *src;
             if ((c2 < 0xDC00) || (c2 > 0xDFFF)) {
-                PutUTF8ReplacementCharacter(dst);
+                if (!PutUTF8ReplacementCharacter(&dst, &dstlen))
+                    goto bufferTooSmall;
                 continue;
             }
             src++;
             srclen--;
             v = ((c - 0xD800) << 10) + (c2 - 0xDC00) + 0x10000;
         }
         size_t utf8Len;
         if (v < 0x0080) {
             /* no encoding necessary - performance hack */
-            *dst++ = char(v);
+            if (dstlen == 0)
+                goto bufferTooSmall;
+            *dst++ = (char) v;
             utf8Len = 1;
         } else {
             uint8_t utf8buf[4];
             utf8Len = js_OneUcs4ToUtf8Char(utf8buf, v);
+            if (utf8Len > dstlen)
+                goto bufferTooSmall;
             for (size_t i = 0; i < utf8Len; i++)
-                *dst++ = char(utf8buf[i]);
+                *dst++ = (char) utf8buf[i];
         }
+        dstlen -= utf8Len;
     }
-}
+    *dstlenp = (origDstlen - dstlen);
+    return true;
 
-JS_PUBLIC_API(void)
-JS::DeflateStringToUTF8Buffer(JSFlatString *src, mozilla::RangedPtr<char> dst)
-{
-    JS::AutoCheckCannotGC nogc;
-    return src->hasLatin1Chars()
-           ? ::DeflateStringToUTF8Buffer(src->latin1Chars(nogc), src->length(), dst)
-           : ::DeflateStringToUTF8Buffer(src->twoByteChars(nogc), src->length(), dst);
+bufferTooSmall:
+    *dstlenp = (origDstlen - dstlen);
+    if (cx->isJSContext()) {
+        js::gc::AutoSuppressGC suppress(cx->asJSContext());
+        JS_ReportErrorNumber(cx->asJSContext(), js_GetErrorMessage, nullptr,
+                             JSMSG_BUFFER_TOO_SMALL);
+    }
+    return false;
 }
 
 template <typename CharT>
 UTF8CharsZ
 JS::CharsToNewUTF8CharsZ(js::ThreadSafeContext *cx, const mozilla::Range<const CharT> chars)
 {
     JS_ASSERT(cx);
 
     /* Get required buffer size. */
     const CharT *str = chars.start().get();
-    size_t len = ::GetDeflatedUTF8StringLength(str, chars.length());
+    size_t len = GetDeflatedUTF8StringLength(str, chars.length());
 
     /* Allocate buffer. */
     char *utf8 = cx->pod_malloc<char>(len + 1);
     if (!utf8)
         return UTF8CharsZ();
 
     /* Encode to UTF8. */
-    ::DeflateStringToUTF8Buffer(str, chars.length(), mozilla::RangedPtr<char>(utf8, len));
+    JS_ALWAYS_TRUE(DeflateStringToUTF8Buffer(cx, str, chars.length(), utf8, &len));
     utf8[len] = '\0';
 
     return UTF8CharsZ(utf8, len);
 }
 
 template UTF8CharsZ
 JS::CharsToNewUTF8CharsZ(js::ThreadSafeContext *cx, const mozilla::Range<const Latin1Char> chars);