Bug 1151149 - Throw if either the target or handler is a revoked proxy in Proxy constructor. r=efaust

This commit is contained in:
Tooru Fujisawa 2015-04-07 18:19:26 +09:00
parent b1c5921060
commit e9f2cb466c
4 changed files with 87 additions and 3 deletions

View File

@ -369,6 +369,7 @@ MSG_DEF(JSMSG_PROXY_CONSTRUCT_OBJECT, 0, JSEXN_TYPEERR, "proxy [[Construct]] mu
MSG_DEF(JSMSG_PROXY_EXTENSIBILITY, 0, JSEXN_TYPEERR, "proxy must report same extensiblitity as target") MSG_DEF(JSMSG_PROXY_EXTENSIBILITY, 0, JSEXN_TYPEERR, "proxy must report same extensiblitity as target")
MSG_DEF(JSMSG_PROXY_GETOWN_OBJORUNDEF, 0, JSEXN_TYPEERR, "proxy [[GetOwnProperty]] must return an object or undefined") MSG_DEF(JSMSG_PROXY_GETOWN_OBJORUNDEF, 0, JSEXN_TYPEERR, "proxy [[GetOwnProperty]] must return an object or undefined")
MSG_DEF(JSMSG_PROXY_REVOKED, 0, JSEXN_TYPEERR, "illegal operation attempted on a revoked proxy") MSG_DEF(JSMSG_PROXY_REVOKED, 0, JSEXN_TYPEERR, "illegal operation attempted on a revoked proxy")
MSG_DEF(JSMSG_PROXY_ARG_REVOKED, 1, JSEXN_TYPEERR, "argument {0} cannot be a revoked proxy")
// Structured cloning // Structured cloning
MSG_DEF(JSMSG_SC_BAD_CLONE_VERSION, 0, JSEXN_ERR, "unsupported structured clone version") MSG_DEF(JSMSG_SC_BAD_CLONE_VERSION, 0, JSEXN_ERR, "unsupported structured clone version")

View File

@ -1175,6 +1175,14 @@ ScriptedDirectProxyHandler::isConstructor(JSObject* obj) const
const char ScriptedDirectProxyHandler::family = 0; const char ScriptedDirectProxyHandler::family = 0;
const ScriptedDirectProxyHandler ScriptedDirectProxyHandler::singleton; const ScriptedDirectProxyHandler ScriptedDirectProxyHandler::singleton;
bool
IsRevokedScriptedProxy(JSObject* obj)
{
obj = CheckedUnwrap(obj);
return obj && IsScriptedProxy(obj) && !obj->as<ProxyObject>().target();
}
// ES6 draft rc4 9.5.15.
static bool static bool
NewScriptedProxy(JSContext* cx, CallArgs& args, const char* callerName) NewScriptedProxy(JSContext* cx, CallArgs& args, const char* callerName)
{ {
@ -1183,26 +1191,48 @@ NewScriptedProxy(JSContext* cx, CallArgs& args, const char* callerName)
callerName, "1", "s"); callerName, "1", "s");
return false; return false;
} }
// Step 1.
RootedObject target(cx, NonNullObject(cx, args[0])); RootedObject target(cx, NonNullObject(cx, args[0]));
if (!target) if (!target)
return false; return false;
// Step 2.
if (IsRevokedScriptedProxy(target)) {
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_PROXY_ARG_REVOKED, "1");
return false;
}
// Step 3.
RootedObject handler(cx, NonNullObject(cx, args[1])); RootedObject handler(cx, NonNullObject(cx, args[1]));
if (!handler) if (!handler)
return false; return false;
// Step 4.
if (IsRevokedScriptedProxy(handler)) {
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_PROXY_ARG_REVOKED, "2");
return false;
}
// Steps 5-6, and 8 (reordered).
RootedValue priv(cx, ObjectValue(*target)); RootedValue priv(cx, ObjectValue(*target));
JSObject* proxy_ = JSObject* proxy_ =
NewProxyObject(cx, &ScriptedDirectProxyHandler::singleton, NewProxyObject(cx, &ScriptedDirectProxyHandler::singleton,
priv, TaggedProto::LazyProto); priv, TaggedProto::LazyProto);
if (!proxy_) if (!proxy_)
return false; return false;
// Step 9 (reordered).
Rooted<ProxyObject*> proxy(cx, &proxy_->as<ProxyObject>()); Rooted<ProxyObject*> proxy(cx, &proxy_->as<ProxyObject>());
proxy->setExtra(ScriptedDirectProxyHandler::HANDLER_EXTRA, ObjectValue(*handler)); proxy->setExtra(ScriptedDirectProxyHandler::HANDLER_EXTRA, ObjectValue(*handler));
// Assign [[Call]] and [[Construct]] // Step 7, Assign [[Call]] and [[Construct]].
uint32_t callable = target->isCallable() ? ScriptedDirectProxyHandler::IS_CALLABLE : 0; uint32_t callable = target->isCallable() ? ScriptedDirectProxyHandler::IS_CALLABLE : 0;
uint32_t constructor = target->isConstructor() ? ScriptedDirectProxyHandler::IS_CONSTRUCTOR : 0; uint32_t constructor = target->isConstructor() ? ScriptedDirectProxyHandler::IS_CONSTRUCTOR : 0;
proxy->as<ProxyObject>().setExtra(ScriptedDirectProxyHandler::IS_CALLCONSTRUCT_EXTRA, proxy->as<ProxyObject>().setExtra(ScriptedDirectProxyHandler::IS_CALLCONSTRUCT_EXTRA,
PrivateUint32Value(callable | constructor)); PrivateUint32Value(callable | constructor));
// Step 10.
args.rval().setObject(*proxy); args.rval().setObject(*proxy);
return true; return true;
} }

View File

@ -0,0 +1,53 @@
var BUGNUMBER = 1151149;
var summary = "Proxy constructor should throw if either the target or handler is a revoked proxy.";
print(BUGNUMBER + ": " + summary);
var p = new Proxy({}, {});
new Proxy(p, {});
new Proxy({}, p);
var r = Proxy.revocable({}, {});
p = r.proxy;
new Proxy(p, {});
new Proxy({}, p);
r.revoke();
assertThrowsInstanceOf(() => new Proxy(p, {}), TypeError);
assertThrowsInstanceOf(() => new Proxy({}, p), TypeError);
var r2 = Proxy.revocable({}, {});
r = Proxy.revocable(r2.proxy, {});
p = r.proxy;
new Proxy(p, {});
new Proxy({}, p);
r2.revoke();
new Proxy(p, {});
new Proxy({}, p);
r.revoke();
assertThrowsInstanceOf(() => new Proxy(p, {}), TypeError);
assertThrowsInstanceOf(() => new Proxy({}, p), TypeError);
var g = newGlobal();
p = g.eval(`var r = Proxy.revocable({}, {}); r.proxy;`);
new Proxy(p, {});
new Proxy({}, p);
g.eval(`r.revoke();`);
assertThrowsInstanceOf(() => new Proxy(p, {}), TypeError);
assertThrowsInstanceOf(() => new Proxy({}, p), TypeError);
if (typeof reportCompare === "function")
reportCompare(true, true);

View File

@ -29,11 +29,11 @@ namespace js {
* *
* https://developer.mozilla.org/en-US/docs/SpiderMonkey/Internals/Bytecode * https://developer.mozilla.org/en-US/docs/SpiderMonkey/Internals/Bytecode
*/ */
static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 273; static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 274;
static const uint32_t XDR_BYTECODE_VERSION = static const uint32_t XDR_BYTECODE_VERSION =
uint32_t(0xb973c0de - XDR_BYTECODE_VERSION_SUBTRAHEND); uint32_t(0xb973c0de - XDR_BYTECODE_VERSION_SUBTRAHEND);
static_assert(JSErr_Limit == 391, static_assert(JSErr_Limit == 392,
"GREETINGS, POTENTIAL SUBTRAHEND INCREMENTER! If you added or " "GREETINGS, POTENTIAL SUBTRAHEND INCREMENTER! If you added or "
"removed MSG_DEFs from js.msg, you should increment " "removed MSG_DEFs from js.msg, you should increment "
"XDR_BYTECODE_VERSION_SUBTRAHEND and update this assertion's " "XDR_BYTECODE_VERSION_SUBTRAHEND and update this assertion's "