Author: olehougaard
Date: Fri Oct 31 02:42:14 2008
New Revision: 665
Modified:
branches/bleeding_edge/src/objects.cc
branches/bleeding_edge/src/objects.h
branches/bleeding_edge/src/runtime.cc
branches/bleeding_edge/test/cctest/test-api.cc
Log:
Introduce access control in propertyIsEnumerable.
Also, fix JSObject::getPropertyAttribute() so it deals correctly with
access control modifiers.
Review URL: http://codereview.chromium.org/8834
Modified: branches/bleeding_edge/src/objects.cc
==============================================================================
--- branches/bleeding_edge/src/objects.cc (original)
+++ branches/bleeding_edge/src/objects.cc Fri Oct 31 02:42:14 2008
@@ -266,6 +266,65 @@
}
+PropertyAttributes JSObject::GetPropertyAttributeWithFailedAccessCheck(
+ Object* receiver,
+ LookupResult* result,
+ String* name,
+ bool continue_search) {
+ if (result->IsValid()) {
+ switch (result->type()) {
+ case CALLBACKS: {
+ // Only allow API accessors.
+ Object* obj = result->GetCallbackObject();
+ if (obj->IsAccessorInfo()) {
+ AccessorInfo* info = AccessorInfo::cast(obj);
+ if (info->all_can_read()) {
+ return result->GetAttributes();
+ }
+ }
+ break;
+ }
+
+ case NORMAL:
+ case FIELD:
+ case CONSTANT_FUNCTION: {
+ // Search ALL_CAN_READ accessors in prototype chain.
+ LookupResult r;
+ result->holder()->LookupRealNamedPropertyInPrototypes(name, &r);
+ if (r.IsValid() && continue_search) {
+ return GetPropertyAttributeWithFailedAccessCheck(receiver,
+ &r,
+ name,
+
continue_search);
+ }
+ break;
+ }
+
+ case INTERCEPTOR: {
+ // If the object has an interceptor, try real named properties.
+ // No access check in GetPropertyAttributeWithInterceptor.
+ LookupResult r;
+ result->holder()->LookupRealNamedProperty(name, &r);
+ if (r.IsValid() && continue_search) {
+ return GetPropertyAttributeWithFailedAccessCheck(receiver,
+ &r,
+ name,
+
continue_search);
+ }
+ break;
+ }
+
+ default: {
+ break;
+ }
+ }
+ }
+
+ Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS);
+ return ABSENT;
+}
+
+
Object* JSObject::GetLazyProperty(Object* receiver,
LookupResult* result,
String* name,
@@ -1720,8 +1779,10 @@
// Check access rights if needed.
if (IsAccessCheckNeeded() &&
!Top::MayNamedAccess(this, name, v8::ACCESS_HAS)) {
- Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS);
- return ABSENT;
+ return GetPropertyAttributeWithFailedAccessCheck(receiver,
+ result,
+ name,
+ continue_search);
}
if (result->IsValid()) {
switch (result->type()) {
Modified: branches/bleeding_edge/src/objects.h
==============================================================================
--- branches/bleeding_edge/src/objects.h (original)
+++ branches/bleeding_edge/src/objects.h Fri Oct 31 02:42:14 2008
@@ -1453,6 +1453,11 @@
PropertyAttributes GetPropertyAttributeWithInterceptor(JSObject*
receiver,
String* name,
bool
continue_search);
+ PropertyAttributes GetPropertyAttributeWithFailedAccessCheck(
+ Object* receiver,
+ LookupResult* result,
+ String* name,
+ bool continue_search);
PropertyAttributes GetPropertyAttribute(JSObject* receiver,
LookupResult* result,
String* name,
Modified: branches/bleeding_edge/src/runtime.cc
==============================================================================
--- branches/bleeding_edge/src/runtime.cc (original)
+++ branches/bleeding_edge/src/runtime.cc Fri Oct 31 02:42:14 2008
@@ -1933,10 +1933,8 @@
return Heap::ToBoolean(object->HasElement(index));
}
- LookupResult result;
- object->LocalLookup(key, &result);
- if (!result.IsProperty()) return Heap::false_value();
- return Heap::ToBoolean(!result.IsDontEnum());
+ PropertyAttributes att = object->GetLocalPropertyAttribute(key);
+ return Heap::ToBoolean(att != ABSENT && att != DONT_ENUM);
}
Modified: branches/bleeding_edge/test/cctest/test-api.cc
==============================================================================
--- branches/bleeding_edge/test/cctest/test-api.cc (original)
+++ branches/bleeding_edge/test/cctest/test-api.cc Fri Oct 31 02:42:14 2008
@@ -3186,6 +3186,41 @@
}
+THREADED_TEST(CrossDomainIsPropertyEnumerable) {
+ 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());
+
+ // env1.prop is enumerable in env2.
+ Local<String> test = v8_str("propertyIsEnumerable.call(env1, 'prop')");
+ {
+ Context::Scope scope_env2(env2);
+ Local<Value> result = Script::Compile(test)->Run();
+ CHECK(result->IsTrue());
+ }
+
+ // Change env2 to a different domain and test again.
+ env2->SetSecurityToken(bar);
+ {
+ Context::Scope scope_env2(env2);
+ Local<Value> result = Script::Compile(test)->Run();
+ CHECK(result->IsFalse());
+ }
+
+ env2.Dispose();
+}
+
+
THREADED_TEST(CrossDomainForIn) {
v8::HandleScope handle_scope;
LocalContext env1;
@@ -3342,7 +3377,7 @@
v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
// Add an accessor that is not accessible by cross-domain JS code.
- global_template->SetAccessor(v8_str("blocked_access_prop"),
+ global_template->SetAccessor(v8_str("blocked_prop"),
UnreachableGetter, UnreachableSetter,
v8::Handle<Value>(),
v8::DEFAULT);
@@ -3368,6 +3403,9 @@
value = v8_compile("other.blocked_prop")->Run();
CHECK(value->IsUndefined());
+ value =
v8_compile("propertyIsEnumerable.call(other, 'blocked_prop')")->Run();
+ CHECK(value->IsFalse());
+
// Access accessible property
value = v8_compile("other.accessible_prop = 3")->Run();
CHECK(value->IsNumber());
@@ -3376,6 +3414,21 @@
value = v8_compile("other.accessible_prop")->Run();
CHECK(value->IsNumber());
CHECK_EQ(3, value->Int32Value());
+
+ value =
+
v8_compile("propertyIsEnumerable.call(other, 'accessible_prop')")->Run();
+ CHECK(value->IsTrue());
+
+ // Enumeration doesn't enumerate accessors from inaccessible objects in
+ // the prototype chain even if the accessors are in themselves
accessible.
+ Local<Value> result =
+ CompileRun("(function(){var obj = {'__proto__':other};"
+ "for (var p in obj)"
+ " if (p == 'accessible_prop' || p == 'blocked_prop') {"
+ " return false;"
+ " }"
+ "return true;})()");
+ CHECK(result->IsTrue());
context1->Exit();
context0->Exit();
--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---