mirror of https://github.com/svaarala/duktape.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
112 lines
3.0 KiB
112 lines
3.0 KiB
/*
|
|
* Bug in test262 test case: ch15/15.12/15.12.2/S15.12.2_A1
|
|
*
|
|
* Duktape does not parse __proto__ as a concrete property when ES6
|
|
* __proto__ property is enabled, but rather sets the object prototype.
|
|
*/
|
|
|
|
/*---
|
|
{
|
|
"knownissue": "when ES6 __proto__ enabled, JSON.parse() parses '__proto__' property incorrectly when a specially crafted reviver is used"
|
|
}
|
|
---*/
|
|
|
|
/*===
|
|
basic case
|
|
[object Object]
|
|
object
|
|
true
|
|
false
|
|
true
|
|
[object Object]
|
|
===*/
|
|
|
|
/*===
|
|
reviver case
|
|
reviver: __proto__
|
|
reviver:
|
|
[object Object]
|
|
object
|
|
true
|
|
false
|
|
true
|
|
[object Object]
|
|
===*/
|
|
|
|
/*===
|
|
complex reviver case
|
|
reviver: foo [object Object] bar
|
|
before: this.__proto__: [object Object]
|
|
after: this.__proto__: undefined
|
|
reviver: __proto__ undefined [object Object]
|
|
reviver: [object Object] [object Object]
|
|
[object Object]
|
|
object
|
|
true
|
|
false
|
|
true
|
|
[object Object]
|
|
===*/
|
|
|
|
function test() {
|
|
var x;
|
|
|
|
function dump(x) {
|
|
print(x);
|
|
print(typeof x);
|
|
print(x instanceof Object);
|
|
print(x instanceof Array);
|
|
print('__proto__' in x);
|
|
print(Object.getOwnPropertyDescriptor(x, '__proto__'));
|
|
}
|
|
|
|
// Basic parse case
|
|
|
|
print('basic case');
|
|
dump(JSON.parse('{"__proto__":[]}'));
|
|
|
|
// Similar issue triggered when reviving '__proto__'
|
|
|
|
print('reviver case');
|
|
dump(JSON.parse('{"__proto__":[]}', function (name, val) {
|
|
// this=holder
|
|
print('reviver:', name);
|
|
return val;
|
|
}));
|
|
|
|
// Here the reviver is quite devious, and modifies the holder
|
|
// so that an own property '__proto__' is removed before that
|
|
// property is revived. Because Duktape writes the replacement
|
|
// value with duk_put_prop() now (in duk_bi_json.c), this runs
|
|
// the risk of doing a normal property put on __proto__ with no
|
|
// such own property in the object -- which then changes the
|
|
// prototype of the result (which is incorrect).
|
|
|
|
print('complex reviver case');
|
|
dump(JSON.parse('{"foo":"bar", "__proto__":[1,2,3]}', function (name, val) {
|
|
// this=holder
|
|
print('reviver:', name, Object.getOwnPropertyDescriptor(this, name), val);
|
|
if (name === 'foo') {
|
|
// Delete '__proto__' while reviving 'foo'.
|
|
print('before: this.__proto__:', Object.getOwnPropertyDescriptor(this, '__proto__'));
|
|
delete this.__proto__;
|
|
print('after: this.__proto__:', Object.getOwnPropertyDescriptor(this, '__proto__'));
|
|
}
|
|
if (name === '__proto__') {
|
|
// Since __proto__ is deleted, duk_bi_json.c will read its value as
|
|
// Object.prototype (= val) before calling us. That's why the test
|
|
// case prints out Object.getOwnPropertyDescriptor(this, name) returning
|
|
// undefined, but 'val' being '[object Object']. Force an array return
|
|
// so that it gets (incorrectly) written to __proto__ using duk_put_prop().
|
|
// The correct behavior here would be to set it as an own property.
|
|
return [];
|
|
}
|
|
return val;
|
|
}));
|
|
}
|
|
|
|
try {
|
|
test();
|
|
} catch (e) {
|
|
print(e);
|
|
}
|
|
|