mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-24 00:24:14 +00:00
Bug 1337564 - Don't use JSON behavior for __proto__ with eval. r=jwalden
Differential Revision: https://phabricator.services.mozilla.com/D45381 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
3778a57619
commit
10bb1ec461
@ -175,7 +175,8 @@ static EvalJSONResult ParseEvalStringAsJSON(
|
||||
chars.begin().get() + 1U, len - 2);
|
||||
|
||||
Rooted<JSONParser<CharT>> parser(
|
||||
cx, JSONParser<CharT>(cx, jsonChars, JSONParserBase::NoError));
|
||||
cx, JSONParser<CharT>(cx, jsonChars,
|
||||
JSONParserBase::ParseType::AttemptForEval));
|
||||
if (!parser.parse(rval)) {
|
||||
return EvalJSON_Failure;
|
||||
}
|
||||
|
@ -1008,7 +1008,8 @@ bool js::ParseJSONWithReviver(JSContext* cx,
|
||||
const mozilla::Range<const CharT> chars,
|
||||
HandleValue reviver, MutableHandleValue vp) {
|
||||
/* 15.12.2 steps 2-3. */
|
||||
Rooted<JSONParser<CharT>> parser(cx, JSONParser<CharT>(cx, chars));
|
||||
Rooted<JSONParser<CharT>> parser(
|
||||
cx, JSONParser<CharT>(cx, chars, JSONParserBase::ParseType::JSONParse));
|
||||
if (!parser.parse(vp)) {
|
||||
return false;
|
||||
}
|
||||
|
25
js/src/jit-test/tests/basic/eval-json-differences.js
Normal file
25
js/src/jit-test/tests/basic/eval-json-differences.js
Normal file
@ -0,0 +1,25 @@
|
||||
load(libdir + "asserts.js");
|
||||
|
||||
// eval({__proto__}) changes [[Prototype]]
|
||||
var obj = eval('({"__proto__": null})');
|
||||
assertEq(Object.getPrototypeOf(obj), null);
|
||||
assertEq(Object.prototype.hasOwnProperty.call(obj, "__proto__"), false);
|
||||
|
||||
// JSON.parse({__proto__}) creates new property __proto__
|
||||
obj = JSON.parse('{"__proto__": null}');
|
||||
assertEq(Object.getPrototypeOf(obj), Object.prototype);
|
||||
assertEq(Object.prototype.hasOwnProperty.call(obj, "__proto__"), true);
|
||||
|
||||
// If __proto__ appears more than once as quoted or unquoted property name in an
|
||||
// object initializer expression, that's an error.
|
||||
//(No other property name has this restriction.)"
|
||||
assertThrowsInstanceOf(() =>
|
||||
eval('({ "__proto__" : null, "__proto__" : null })'), SyntaxError);
|
||||
|
||||
assertThrowsInstanceOf(() =>
|
||||
eval(' ({ "__proto__" : null, "__proto__" : null })'), SyntaxError);
|
||||
|
||||
// JSON.parse doesn't care about duplication, the last definition counts.
|
||||
obj = JSON.parse('{"__proto__": null, "__proto__": 5}');
|
||||
assertEq(Object.getPrototypeOf(obj), Object.prototype);
|
||||
assertEq(obj["__proto__"], 5);
|
@ -77,7 +77,7 @@ void JSONParser<CharT>::getTextPosition(uint32_t* column, uint32_t* line) {
|
||||
|
||||
template <typename CharT>
|
||||
void JSONParser<CharT>::error(const char* msg) {
|
||||
if (errorHandling == RaiseError) {
|
||||
if (parseType == ParseType::JSONParse) {
|
||||
uint32_t column = 1, line = 1;
|
||||
getTextPosition(&column, &line);
|
||||
|
||||
@ -93,7 +93,9 @@ void JSONParser<CharT>::error(const char* msg) {
|
||||
}
|
||||
}
|
||||
|
||||
bool JSONParserBase::errorReturn() { return errorHandling == NoError; }
|
||||
bool JSONParserBase::errorReturn() {
|
||||
return parseType == ParseType::AttemptForEval;
|
||||
}
|
||||
|
||||
template <typename CharT>
|
||||
template <JSONParserBase::StringType ST>
|
||||
@ -666,6 +668,17 @@ bool JSONParser<CharT>::parse(MutableHandleValue vp) {
|
||||
JSONMember:
|
||||
if (token == String) {
|
||||
jsid id = AtomToId(atomValue());
|
||||
if (parseType == ParseType::AttemptForEval) {
|
||||
// In |JSON.parse|, "__proto__" is a property like any other and may
|
||||
// appear multiple times. In object literal syntax, "__proto__" is
|
||||
// prototype mutation and can appear at most once. |JSONParser| only
|
||||
// supports the former semantics, so if this parse attempt is for
|
||||
// |eval|, return true (without reporting an error) to indicate the
|
||||
// JSON parse attempt was unsuccessful.
|
||||
if (id == NameToId(cx->names().proto)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
PropertyVector& properties = stack.back().properties();
|
||||
if (!properties.append(IdValuePair(id))) {
|
||||
return false;
|
||||
|
@ -22,7 +22,14 @@ namespace js {
|
||||
// can be shared between the two encodings.
|
||||
class MOZ_STACK_CLASS JSONParserBase {
|
||||
public:
|
||||
enum ErrorHandling { RaiseError, NoError };
|
||||
enum class ParseType {
|
||||
// Parsing a string as if by JSON.parse.
|
||||
JSONParse,
|
||||
// Parsing what may or may not be JSON in a string of eval code.
|
||||
// In this case, a failure to parse indicates either syntax that isn't JSON,
|
||||
// or syntax that has different semantics in eval code than in JSON.
|
||||
AttemptForEval,
|
||||
};
|
||||
|
||||
private:
|
||||
/* Data members */
|
||||
@ -31,7 +38,7 @@ class MOZ_STACK_CLASS JSONParserBase {
|
||||
protected:
|
||||
JSContext* const cx;
|
||||
|
||||
const ErrorHandling errorHandling;
|
||||
const ParseType parseType;
|
||||
|
||||
enum Token {
|
||||
String,
|
||||
@ -114,9 +121,9 @@ class MOZ_STACK_CLASS JSONParserBase {
|
||||
Token lastToken;
|
||||
#endif
|
||||
|
||||
JSONParserBase(JSContext* cx, ErrorHandling errorHandling)
|
||||
JSONParserBase(JSContext* cx, ParseType parseType)
|
||||
: cx(cx),
|
||||
errorHandling(errorHandling),
|
||||
parseType(parseType),
|
||||
stack(cx),
|
||||
freeElements(cx),
|
||||
freeProperties(cx)
|
||||
@ -132,7 +139,7 @@ class MOZ_STACK_CLASS JSONParserBase {
|
||||
JSONParserBase(JSONParserBase&& other)
|
||||
: v(other.v),
|
||||
cx(other.cx),
|
||||
errorHandling(other.errorHandling),
|
||||
parseType(other.parseType),
|
||||
stack(std::move(other.stack)),
|
||||
freeElements(std::move(other.freeElements)),
|
||||
freeProperties(std::move(other.freeProperties))
|
||||
@ -212,8 +219,8 @@ class MOZ_STACK_CLASS JSONParser : public JSONParserBase {
|
||||
|
||||
/* Create a parser for the provided JSON data. */
|
||||
JSONParser(JSContext* cx, mozilla::Range<const CharT> data,
|
||||
ErrorHandling errorHandling = RaiseError)
|
||||
: JSONParserBase(cx, errorHandling),
|
||||
ParseType parseType)
|
||||
: JSONParserBase(cx, parseType),
|
||||
current(data.begin()),
|
||||
begin(current),
|
||||
end(data.end()) {
|
||||
|
Loading…
Reference in New Issue
Block a user