Bug 1026680 part 4 - Cleanup str_escape. r=njn
authorJan de Mooij <jdemooij@mozilla.com>
Wed, 18 Jun 2014 11:33:52 +0200
changeset 189453 fd9bc8054cdd0098c0cb870e44d4df4304c979f2
parent 189452 f65a139220496c4740599061003b7762b3c389ce
child 189454 0784505c202aea8b270f2fa7b1622f4b1a9f16f8
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersnjn
bugs1026680
milestone33.0a1
Bug 1026680 part 4 - Cleanup str_escape. r=njn
js/src/jsstr.cpp
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -113,77 +113,58 @@ str_encodeURI_Component(JSContext *cx, u
 
 
 /* ES5 B.2.1 */
 static bool
 str_escape(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
-    static const char digits[] = {'0', '1', '2', '3', '4', '5', '6', '7',
-                                  '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
-
     JSLinearString *str = ArgToRootedString(cx, args, 0);
     if (!str)
         return false;
 
-    size_t length = str->length();
+    uint32_t length = str->length();
     const jschar *chars = str->chars();
 
-    static const uint8_t shouldPassThrough[256] = {
+    static const uint8_t shouldPassThrough[128] = {
          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
          0,0,0,0,0,0,0,0,0,0,1,1,0,1,1,1,       /*    !"#$%&'()*+,-./  */
          1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,       /*   0123456789:;<=>?  */
          1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,       /*   @ABCDEFGHIJKLMNO  */
          1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,       /*   PQRSTUVWXYZ[\]^_  */
          0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,       /*   `abcdefghijklmno  */
-         1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,     /*   pqrstuvwxyz{\}~  DEL */
+         1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,       /*   pqrstuvwxyz{\}~  DEL */
     };
 
-    /* In step 7, exactly 69 characters should pass through unencoded. */
-#ifdef DEBUG
-    size_t count = 0;
-    for (size_t i = 0; i < sizeof(shouldPassThrough); i++) {
-        if (shouldPassThrough[i]) {
-            count++;
-        }
-    }
-    JS_ASSERT(count == 69);
-#endif
-
-
     /* Take a first pass and see how big the result string will need to be. */
-    size_t newlength = length;
+    uint32_t newlength = length;
     for (size_t i = 0; i < length; i++) {
         jschar ch = chars[i];
         if (ch < 128 && shouldPassThrough[ch])
             continue;
 
         /* The character will be encoded as %XX or %uXXXX. */
         newlength += (ch < 256) ? 2 : 5;
 
         /*
-         * This overflow test works because newlength is incremented by at
-         * most 5 on each iteration.
+         * newlength is incremented by at most 5 on each iteration, so worst
+         * case newlength == length * 6. This can't overflow.
          */
-        if (newlength < length) {
-            js_ReportAllocationOverflow(cx);
-            return false;
-        }
+        static_assert(JSString::MAX_LENGTH < UINT32_MAX / 6,
+                      "newlength must not overflow");
     }
 
-    if (newlength >= ~(size_t)0 / sizeof(jschar)) {
-        js_ReportAllocationOverflow(cx);
-        return false;
-    }
-
-    jschar *newchars = cx->pod_malloc<jschar>(newlength + 1);
+    ScopedJSFreePtr<jschar> newchars(cx->pod_malloc<jschar>(newlength + 1));
     if (!newchars)
         return false;
+
+    static const char digits[] = "0123456789ABCDEF";
+
     size_t i, ni;
     for (i = 0, ni = 0; i < length; i++) {
         jschar ch = chars[i];
         if (ch < 128 && shouldPassThrough[ch]) {
             newchars[ni++] = ch;
         } else if (ch < 256) {
             newchars[ni++] = '%';
             newchars[ni++] = digits[ch >> 4];
@@ -195,22 +176,21 @@ str_escape(JSContext *cx, unsigned argc,
             newchars[ni++] = digits[(ch & 0xF00) >> 8];
             newchars[ni++] = digits[(ch & 0xF0) >> 4];
             newchars[ni++] = digits[ch & 0xF];
         }
     }
     JS_ASSERT(ni == newlength);
     newchars[newlength] = 0;
 
-    JSString *retstr = js_NewString<CanGC>(cx, newchars, newlength);
-    if (!retstr) {
-        js_free(newchars);
+    JSString *retstr = js_NewString<CanGC>(cx, newchars.get(), newlength);
+    if (!retstr)
         return false;
-    }
-
+
+    newchars.forget();
     args.rval().setString(retstr);
     return true;
 }
 
 template <typename CharT>
 static inline bool
 Unhex4(const RangedPtr<const CharT> chars, jschar *result)
 {