static bool EvalStringMightBeJSON(const mozilla::Range<const CharT> chars) { // If the eval string starts with '(' or '[' and ends with ')' or ']', it may be JSON. // Try the JSON parser first because it's much faster. If the eval string // isn't JSON, JSON parsing will probably fail quickly, so little time // will be lost. size_t length = chars.length(); if (length > 2 && ((chars[0] == '[' && chars[length - 1] == ']') || (chars[0] == '(' && chars[length - 1] == ')'))) { // Remarkably, JavaScript syntax is not a superset of JSON syntax: // strings in JavaScript cannot contain the Unicode line and paragraph // terminator characters U+2028 and U+2029, but strings in JSON can. // Rather than force the JSON parser to handle this quirk when used by // eval, we simply don't use the JSON parser when either character // appears in the provided string. See bug 657367. if (sizeof(CharT) > 1) { for (RangedPtr<const CharT> cp = chars.start() + 1, end = chars.end() - 1; cp < end; cp++) { char16_t c = *cp; if (c == 0x2028 || c == 0x2029) return false; } } return true; } return false; }
static bool ArgsAndBodySubstring(mozilla::Range<const CharT> chars, size_t *outOffset, size_t *outLen) { const CharT *const start = chars.start().get(); const CharT *const end = chars.end().get(); const CharT *s = start; uint8_t parenChomp = 0; if (s[0] == '(') { s++; parenChomp = 1; } /* Try to jump "function" keyword. */ s = js_strchr_limit(s, ' ', end); if (!s) return false; /* * Jump over the function's name: it can't be encoded as part * of an ECMA getter or setter. */ s = js_strchr_limit(s, '(', end); if (!s) return false; if (*s == ' ') s++; *outOffset = s - start; *outLen = end - s - parenChomp; MOZ_ASSERT(*outOffset + *outLen <= chars.length()); return true; }
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()); /* 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)); utf8[len] = '\0'; return UTF8CharsZ(utf8, len); }
UTF8CharsZ JS::CharsToNewUTF8CharsZ(js::ExclusiveContext* maybeCx, const mozilla::Range<CharT> chars) { /* Get required buffer size. */ const CharT* str = chars.start().get(); size_t len = ::GetDeflatedUTF8StringLength(str, chars.length()); /* Allocate buffer. */ char* utf8; if (maybeCx) utf8 = maybeCx->pod_malloc<char>(len + 1); else utf8 = js_pod_malloc<char>(len + 1); if (!utf8) return UTF8CharsZ(); /* Encode to UTF8. */ ::DeflateStringToUTF8Buffer(str, chars.length(), mozilla::RangedPtr<char>(utf8, len)); utf8[len] = '\0'; return UTF8CharsZ(utf8, len); }
Latin1CharsZ JS::LossyTwoByteCharsToNewLatin1CharsZ(js::ThreadSafeContext *cx, const mozilla::Range<const jschar> tbchars) { JS_ASSERT(cx); size_t len = tbchars.length(); unsigned char *latin1 = cx->pod_malloc<unsigned char>(len + 1); if (!latin1) return Latin1CharsZ(); for (size_t i = 0; i < len; ++i) latin1[i] = static_cast<unsigned char>(tbchars[i]); latin1[len] = '\0'; return Latin1CharsZ(latin1, len); }
static EvalJSONResult ParseEvalStringAsJSON(JSContext *cx, const mozilla::Range<const CharT> chars, MutableHandleValue rval) { size_t len = chars.length(); MOZ_ASSERT((chars[0] == '(' && chars[len - 1] == ')') || (chars[0] == '[' && chars[len - 1] == ']')); auto jsonChars = (chars[0] == '[') ? chars : mozilla::Range<const CharT>(chars.start().get() + 1U, len - 2); JSONParser<CharT> parser(cx, jsonChars, JSONParserBase::NoError); if (!parser.parse(rval)) return EvalJSON_Failure; return rval.isUndefined() ? EvalJSON_NotJSON : EvalJSON_Success; }