Commit 21bd4564 authored by adamk's avatar adamk Committed by Commit bot

Disallow Object.observe calls on access-checked objects

We already disallowed observing the global proxy; now we also
disallow any observation of access-checked objects (regardless
of whether the access check would succeed or fail, since there's
not a good way to tell the embedder what kind of access is being
requested).

Also disallow Object.getNotifier for the same reasons.

BUG=chromium:531891
LOG=y

Review URL: https://codereview.chromium.org/1346813002

Cr-Commit-Position: refs/heads/master@{#30774}
parent d346834f
......@@ -160,6 +160,7 @@ class CallSite {
T(ObserveCallbackFrozen, \
"Object.observe cannot deliver to a frozen function object") \
T(ObserveGlobalProxy, "% cannot be called on the global proxy object") \
T(ObserveAccessChecked, "% cannot be called on access-checked objects") \
T(ObserveInvalidAccept, \
"Third argument to Object.observe must be an array of strings.") \
T(ObserveNonFunction, "Object.% cannot deliver to non-function") \
......
......@@ -388,6 +388,8 @@ function ObjectObserve(object, callback, acceptList) {
throw MakeTypeError(kObserveNonObject, "observe", "observe");
if (%IsJSGlobalProxy(object))
throw MakeTypeError(kObserveGlobalProxy, "observe");
if (%IsAccessCheckNeeded(object))
throw MakeTypeError(kObserveAccessChecked, "observe");
if (!IS_CALLABLE(callback))
throw MakeTypeError(kObserveNonFunction, "observe");
if (ObjectIsFrozen(callback))
......@@ -616,6 +618,8 @@ function ObjectGetNotifier(object) {
throw MakeTypeError(kObserveNonObject, "getNotifier", "getNotifier");
if (%IsJSGlobalProxy(object))
throw MakeTypeError(kObserveGlobalProxy, "getNotifier");
if (%IsAccessCheckNeeded(object))
throw MakeTypeError(kObserveAccessChecked, "getNotifier");
if (ObjectIsFrozen(object)) return null;
......
......@@ -1547,5 +1547,14 @@ RUNTIME_FUNCTION(Runtime_CreateIterResultObject) {
return *isolate->factory()->NewJSIteratorResult(value, done);
}
RUNTIME_FUNCTION(Runtime_IsAccessCheckNeeded) {
SealHandleScope shs(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_CHECKED(Object, object, 0);
return isolate->heap()->ToBoolean(object->IsAccessCheckNeeded());
}
} // namespace internal
} // namespace v8
......@@ -482,7 +482,8 @@ namespace internal {
F(StrictEquals, 2, 1) \
F(InstanceOf, 2, 1) \
F(HasInPrototypeChain, 2, 1) \
F(CreateIterResultObject, 2, 1)
F(CreateIterResultObject, 2, 1) \
F(IsAccessCheckNeeded, 1, 1)
#define FOR_EACH_INTRINSIC_OBSERVE(F) \
......
......@@ -885,3 +885,39 @@ TEST(UseCountObjectGetNotifier) {
CompileRun("Object.getNotifier(obj)");
CHECK_EQ(1, use_counts[v8::Isolate::kObjectObserve]);
}
static bool NamedAccessCheckAlwaysAllow(Local<v8::Object> global,
Local<v8::Value> name,
v8::AccessType type,
Local<Value> data) {
return true;
}
TEST(DisallowObserveAccessCheckedObject) {
v8::Isolate* isolate = CcTest::isolate();
v8::HandleScope scope(isolate);
LocalContext env;
v8::Local<v8::ObjectTemplate> object_template =
v8::ObjectTemplate::New(isolate);
object_template->SetAccessCheckCallbacks(NamedAccessCheckAlwaysAllow, NULL);
env->Global()->Set(v8_str("obj"), object_template->NewInstance());
v8::TryCatch try_catch(isolate);
CompileRun("Object.observe(obj, function(){})");
CHECK(try_catch.HasCaught());
}
TEST(DisallowGetNotifierAccessCheckedObject) {
v8::Isolate* isolate = CcTest::isolate();
v8::HandleScope scope(isolate);
LocalContext env;
v8::Local<v8::ObjectTemplate> object_template =
v8::ObjectTemplate::New(isolate);
object_template->SetAccessCheckCallbacks(NamedAccessCheckAlwaysAllow, NULL);
env->Global()->Set(v8_str("obj"), object_template->NewInstance());
v8::TryCatch try_catch(isolate);
CompileRun("Object.getNotifier(obj)");
CHECK(try_catch.HasCaught());
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment