This is a fix of issue http://b/issue?id=1381845.
authorfeng@chromium.org <feng@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 24 Sep 2008 15:47:34 +0000 (15:47 +0000)
committerfeng@chromium.org <feng@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 24 Sep 2008 15:47:34 +0000 (15:47 +0000)
Check domain security on prototypes in for-in loop.

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

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

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

index 1fbb8ae..8c1b957 100644 (file)
@@ -332,13 +332,6 @@ v8::Handle<v8::Array> GetKeysForIndexedInterceptor(Handle<JSObject> receiver,
 Handle<FixedArray> GetKeysInFixedArrayFor(Handle<JSObject> object) {
   Handle<FixedArray> content = Factory::empty_fixed_array();
 
-  // Check access rights if required.
-  if (object->IsAccessCheckNeeded() &&
-    !Top::MayNamedAccess(*object, Heap::undefined_value(), v8::ACCESS_KEYS)) {
-    Top::ReportFailedAccessCheck(*object, v8::ACCESS_KEYS);
-    return content;
-  }
-
   JSObject* arguments_boilerplate =
       Top::context()->global_context()->arguments_boilerplate();
   JSFunction* arguments_function =
@@ -352,6 +345,14 @@ Handle<FixedArray> GetKeysInFixedArrayFor(Handle<JSObject> object) {
          p = Handle<Object>(p->GetPrototype())) {
       Handle<JSObject> current(JSObject::cast(*p));
 
+      // Check access rights if required.
+      if (current->IsAccessCheckNeeded() &&
+        !Top::MayNamedAccess(*current, Heap::undefined_value(),
+                             v8::ACCESS_KEYS)) {
+        Top::ReportFailedAccessCheck(*current, v8::ACCESS_KEYS);
+        break;
+      }
+
       // Compute the property keys.
       content = UnionOfKeys(content, GetEnumPropertyKeys(current));
 
index 800cc8b..7c80c53 100644 (file)
@@ -3167,6 +3167,38 @@ THREADED_TEST(CrossDomainDelete) {
 }
 
 
+THREADED_TEST(CrossDomainForIn) {
+  v8::HandleScope handle_scope;
+  LocalContext env1;
+  v8::Persistent<Context> env2 = Context::New();
+
+  Local<Value> foo = v8_str("foo");
+  Local<Value> bar = v8_str("bar");
+
+  // Set to the same domain.
+  env1->SetSecurityToken(foo);
+  env2->SetSecurityToken(foo);
+
+  env1->Global()->Set(v8_str("prop"), v8_num(3));
+  env2->Global()->Set(v8_str("env1"), env1->Global());
+
+  // Change env2 to a different domain and set env1's global object
+  // as the __proto__ of an object in env2 and enumerate properties
+  // in for-in. It shouldn't enumerate properties on env1's global
+  // object.
+  env2->SetSecurityToken(bar);
+  {
+    Context::Scope scope_env2(env2);
+    Local<Value> result =
+        CompileRun("(function(){var obj = {'__proto__':env1};"
+                   "for (var p in obj)"
+                   "   if (p == 'prop') return false;"
+                   "return true;})()");
+    CHECK(result->IsTrue());
+  }
+  env2.Dispose();
+}
+
 
 static bool NamedAccessBlocker(Local<v8::Object> global,
                                Local<Value> name,