Bug 876639 - Address unsafe references from JS_ParseJSON() - Fix shell r=terrence

This commit is contained in:
Jon Coppeard 2013-05-29 09:28:03 +01:00
parent 16a933bf77
commit 9ddc84ce1b
3 changed files with 51 additions and 32 deletions

View File

@ -46,54 +46,78 @@ NewString(JSContext *cx, const jschar (&chars)[N])
BEGIN_TEST(testParseJSON_success)
{
// Primitives
CHECK(TryParse(cx, "true", JSVAL_TRUE));
CHECK(TryParse(cx, "false", JSVAL_FALSE));
CHECK(TryParse(cx, "null", JSVAL_NULL));
CHECK(TryParse(cx, "0", INT_TO_JSVAL(0)));
CHECK(TryParse(cx, "1", INT_TO_JSVAL(1)));
CHECK(TryParse(cx, "-1", INT_TO_JSVAL(-1)));
CHECK(TryParse(cx, "1", DOUBLE_TO_JSVAL(1)));
CHECK(TryParse(cx, "1.75", DOUBLE_TO_JSVAL(1.75)));
CHECK(TryParse(cx, "9e9", DOUBLE_TO_JSVAL(9e9)));
CHECK(TryParse(cx, "9e99999", DOUBLE_TO_JSVAL(std::numeric_limits<double>::infinity())));
JS::RootedValue expected(cx);
expected = JSVAL_TRUE;
CHECK(TryParse(cx, "true", expected));
expected = JSVAL_FALSE;
CHECK(TryParse(cx, "false", expected));
expected = JSVAL_NULL;
CHECK(TryParse(cx, "null", expected));
expected = INT_TO_JSVAL(0);
CHECK(TryParse(cx, "0", expected));
expected = INT_TO_JSVAL(1);
CHECK(TryParse(cx, "1", expected));
expected = INT_TO_JSVAL(-1);
CHECK(TryParse(cx, "-1", expected));
expected = DOUBLE_TO_JSVAL(1);
CHECK(TryParse(cx, "1", expected));
expected = DOUBLE_TO_JSVAL(1.75);
CHECK(TryParse(cx, "1.75", expected));
expected = DOUBLE_TO_JSVAL(9e9);
CHECK(TryParse(cx, "9e9", expected));
expected = DOUBLE_TO_JSVAL(std::numeric_limits<double>::infinity());
CHECK(TryParse(cx, "9e99999", expected));
JS::Rooted<JSFlatString*> str(cx);
const jschar emptystr[] = { '\0' };
str = js_NewStringCopyN<CanGC>(cx, emptystr, 0);
CHECK(str);
CHECK(TryParse(cx, "\"\"", STRING_TO_JSVAL(str)));
expected = STRING_TO_JSVAL(str);
CHECK(TryParse(cx, "\"\"", expected));
const jschar nullstr[] = { '\0' };
str = NewString(cx, nullstr);
CHECK(str);
CHECK(TryParse(cx, "\"\\u0000\"", STRING_TO_JSVAL(str)));
expected = STRING_TO_JSVAL(str);
CHECK(TryParse(cx, "\"\\u0000\"", expected));
const jschar backstr[] = { '\b' };
str = NewString(cx, backstr);
CHECK(str);
CHECK(TryParse(cx, "\"\\b\"", STRING_TO_JSVAL(str)));
CHECK(TryParse(cx, "\"\\u0008\"", STRING_TO_JSVAL(str)));
expected = STRING_TO_JSVAL(str);
CHECK(TryParse(cx, "\"\\b\"", expected));
CHECK(TryParse(cx, "\"\\u0008\"", expected));
const jschar newlinestr[] = { '\n', };
str = NewString(cx, newlinestr);
CHECK(str);
CHECK(TryParse(cx, "\"\\n\"", STRING_TO_JSVAL(str)));
CHECK(TryParse(cx, "\"\\u000A\"", STRING_TO_JSVAL(str)));
expected = STRING_TO_JSVAL(str);
CHECK(TryParse(cx, "\"\\n\"", expected));
CHECK(TryParse(cx, "\"\\u000A\"", expected));
// Arrays
JS::RootedValue v(cx), v2(cx);
JS::RootedObject obj(cx);
CHECK(Parse(cx, "[]", v.address()));
CHECK(Parse(cx, "[]", &v));
CHECK(!JSVAL_IS_PRIMITIVE(v));
obj = JSVAL_TO_OBJECT(v);
CHECK(JS_IsArrayObject(cx, obj));
CHECK(JS_GetProperty(cx, obj, "length", v2.address()));
CHECK_SAME(v2, JSVAL_ZERO);
CHECK(Parse(cx, "[1]", v.address()));
CHECK(Parse(cx, "[1]", &v));
CHECK(!JSVAL_IS_PRIMITIVE(v));
obj = JSVAL_TO_OBJECT(v);
CHECK(JS_IsArrayObject(cx, obj));
@ -104,12 +128,12 @@ BEGIN_TEST(testParseJSON_success)
// Objects
CHECK(Parse(cx, "{}", v.address()));
CHECK(Parse(cx, "{}", &v));
CHECK(!JSVAL_IS_PRIMITIVE(v));
obj = JSVAL_TO_OBJECT(v);
CHECK(!JS_IsArrayObject(cx, obj));
CHECK(Parse(cx, "{ \"f\": 17 }", v.address()));
CHECK(Parse(cx, "{ \"f\": 17 }", &v));
CHECK(!JSVAL_IS_PRIMITIVE(v));
obj = JSVAL_TO_OBJECT(v);
CHECK(!JS_IsArrayObject(cx, obj));
@ -120,7 +144,7 @@ BEGIN_TEST(testParseJSON_success)
}
template<size_t N> inline bool
Parse(JSContext *cx, const char (&input)[N], jsval *vp)
Parse(JSContext *cx, const char (&input)[N], JS::MutableHandleValue vp)
{
AutoInflatedString str(cx);
str = input;
@ -129,13 +153,12 @@ Parse(JSContext *cx, const char (&input)[N], jsval *vp)
}
template<size_t N> inline bool
TryParse(JSContext *cx, const char (&input)[N], const jsval &expectedArg)
TryParse(JSContext *cx, const char (&input)[N], JS::HandleValue expected)
{
AutoInflatedString str(cx);
JS::RootedValue expected(cx, expectedArg);
RootedValue v(cx);
str = input;
CHECK(JS_ParseJSON(cx, str.chars(), str.length(), v.address()));
CHECK(JS_ParseJSON(cx, str.chars(), str.length(), &v));
CHECK_SAME(v, expected);
return true;
}
@ -160,7 +183,7 @@ template<size_t N> inline bool
Error(JSContext *cx, const char (&input)[N])
{
AutoInflatedString str(cx);
jsval dummy;
RootedValue dummy(cx);
str = input;
ContextPrivate p = {0, 0};

View File

@ -6353,17 +6353,13 @@ JS_Stringify(JSContext *cx, jsval *vp, JSObject *replacerArg, jsval space,
}
JS_PUBLIC_API(JSBool)
JS_ParseJSON(JSContext *cx, const jschar *chars, uint32_t len, jsval *vp)
JS_ParseJSON(JSContext *cx, const jschar *chars, uint32_t len, JS::MutableHandleValue vp)
{
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
RootedValue reviver(cx, NullValue()), value(cx);
if (!ParseJSONWithReviver(cx, JS::StableCharPtr(chars, len), len, reviver, &value))
return false;
*vp = value;
return true;
return ParseJSONWithReviver(cx, JS::StableCharPtr(chars, len), len, reviver, vp);
}
JS_PUBLIC_API(JSBool)

View File

@ -4478,7 +4478,7 @@ JS_Stringify(JSContext *cx, jsval *vp, JSObject *replacer, jsval space,
* JSON.parse as specified by ES5.
*/
JS_PUBLIC_API(JSBool)
JS_ParseJSON(JSContext *cx, const jschar *chars, uint32_t len, jsval *vp);
JS_ParseJSON(JSContext *cx, const jschar *chars, uint32_t len, JS::MutableHandle<JS::Value> vp);
JS_PUBLIC_API(JSBool)
JS_ParseJSONWithReviver(JSContext *cx, const jschar *chars, uint32_t len, jsval reviver,