Add access check when Object.keys is called on the global js proxy (fixes issue 1154)
authorricow@chromium.org <ricow@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 15 Feb 2011 10:39:22 +0000 (10:39 +0000)
committerricow@chromium.org <ricow@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 15 Feb 2011 10:39:22 +0000 (10:39 +0000)
I will land access checks for a range of ES5 features in another patch (we added a bunch of cases like this in the past few weeks, i.e., cases where we simply use the global object instead of the js global proxy).

Review URL: http://codereview.chromium.org/6499013

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6786 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/runtime.cc
test/cctest/test-api.cc

index b83164e..81ce7e4 100644 (file)
@@ -4217,6 +4217,14 @@ static MaybeObject* Runtime_LocalKeys(Arguments args) {
   Handle<JSObject> object(raw_object);
 
   if (object->IsJSGlobalProxy()) {
+    // Do access checks before going to the global object.
+    if (object->IsAccessCheckNeeded() &&
+        !Top::MayNamedAccess(*object, Heap::undefined_value(),
+                             v8::ACCESS_KEYS)) {
+      Top::ReportFailedAccessCheck(*object, v8::ACCESS_KEYS);
+      return *Factory::NewJSArray(0);
+    }
+
     Handle<Object> proto(object->GetPrototype());
     // If proxy is detached we simply return an empty array.
     if (proto->IsNull()) return *Factory::NewJSArray(0);
index e711dc8..ded42b4 100644 (file)
@@ -5617,6 +5617,35 @@ TEST(AccessControl) {
 }
 
 
+// This is a regression test for issue 1154.
+TEST(AccessControlObjectKeys) {
+  v8::HandleScope handle_scope;
+  v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
+
+  global_template->SetAccessCheckCallbacks(NamedAccessBlocker,
+                                           IndexedAccessBlocker);
+
+  // Add an accessor that is not accessible by cross-domain JS code.
+  global_template->SetAccessor(v8_str("blocked_prop"),
+                               UnreachableGetter, UnreachableSetter,
+                               v8::Handle<Value>(),
+                               v8::DEFAULT);
+
+  // Create an environment
+  v8::Persistent<Context> context0 = Context::New(NULL, global_template);
+  context0->Enter();
+
+  v8::Handle<v8::Object> global0 = context0->Global();
+
+  v8::Persistent<Context> context1 = Context::New();
+  context1->Enter();
+  v8::Handle<v8::Object> global1 = context1->Global();
+  global1->Set(v8_str("other"), global0);
+
+  ExpectTrue("Object.keys(other).indexOf('blocked_prop') == -1");
+}
+
+
 static bool GetOwnPropertyNamesNamedBlocker(Local<v8::Object> global,
                                             Local<Value> name,
                                             v8::AccessType type,