From d69237f415bfdf4462320255978061e52832cffa Mon Sep 17 00:00:00 2001 From: Jan de Mooij Date: Wed, 18 Jun 2014 11:33:52 +0200 Subject: [PATCH] Bug 1026680 part 4 - Cleanup str_escape. r=njn --- js/src/jsstr.cpp | 50 +++++++++++++++--------------------------------- 1 file changed, 15 insertions(+), 35 deletions(-) diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp index ebc3757b8c8c..5295bbf551cb 100644 --- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -118,17 +118,14 @@ 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, /* !"#$%&'()*+,-./ */ @@ -136,23 +133,11 @@ str_escape(JSContext *cx, unsigned argc, Value *vp) 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]) @@ -162,23 +147,19 @@ str_escape(JSContext *cx, unsigned argc, Value *vp) 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(newlength + 1); + ScopedJSFreePtr newchars(cx->pod_malloc(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]; @@ -200,12 +181,11 @@ str_escape(JSContext *cx, unsigned argc, Value *vp) JS_ASSERT(ni == newlength); newchars[newlength] = 0; - JSString *retstr = js_NewString(cx, newchars, newlength); - if (!retstr) { - js_free(newchars); + JSString *retstr = js_NewString(cx, newchars.get(), newlength); + if (!retstr) return false; - } + newchars.forget(); args.rval().setString(retstr); return true; }