Add missing access checks to Object.getOwnPropertyNames.

Makes webkit layout test: http/tests/security/cross-frame-access-enumeration.html fail.
Review URL: http://codereview.chromium.org/561019

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3771 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
ager@chromium.org 2010-02-02 13:48:54 +00:00
parent c9c504770a
commit c4bd2aa054
2 changed files with 73 additions and 0 deletions

View File

@ -3251,6 +3251,12 @@ static Object* Runtime_GetLocalPropertyNames(Arguments args) {
// Skip the global proxy as it has no properties and always delegates to the
// real global object.
if (obj->IsJSGlobalProxy()) {
// Only collect names if access is permitted.
if (obj->IsAccessCheckNeeded() &&
!Top::MayNamedAccess(*obj, Heap::undefined_value(), v8::ACCESS_KEYS)) {
Top::ReportFailedAccessCheck(*obj, v8::ACCESS_KEYS);
return *Factory::NewJSArray(0);
}
obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype()));
}
@ -3262,6 +3268,14 @@ static Object* Runtime_GetLocalPropertyNames(Arguments args) {
int total_property_count = 0;
Handle<JSObject> jsproto = obj;
for (int i = 0; i < length; i++) {
// Only collect names if access is permitted.
if (jsproto->IsAccessCheckNeeded() &&
!Top::MayNamedAccess(*jsproto,
Heap::undefined_value(),
v8::ACCESS_KEYS)) {
Top::ReportFailedAccessCheck(*jsproto, v8::ACCESS_KEYS);
return *Factory::NewJSArray(0);
}
int n;
n = jsproto->NumberOfLocalProperties(static_cast<PropertyAttributes>(NONE));
local_property_count[i] = n;

View File

@ -4124,6 +4124,65 @@ THREADED_TEST(AccessControl) {
}
static bool GetOwnPropertyNamesNamedBlocker(Local<v8::Object> global,
Local<Value> name,
v8::AccessType type,
Local<Value> data) {
return false;
}
static bool GetOwnPropertyNamesIndexedBlocker(Local<v8::Object> global,
uint32_t key,
v8::AccessType type,
Local<Value> data) {
return false;
}
THREADED_TEST(AccessControlGetOwnPropertyNames) {
v8::HandleScope handle_scope;
v8::Handle<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New();
obj_template->Set(v8_str("x"), v8::Integer::New(42));
obj_template->SetAccessCheckCallbacks(GetOwnPropertyNamesNamedBlocker,
GetOwnPropertyNamesIndexedBlocker);
// Create an environment
v8::Persistent<Context> context0 = Context::New(NULL, obj_template);
context0->Enter();
v8::Handle<v8::Object> global0 = context0->Global();
v8::HandleScope scope1;
v8::Persistent<Context> context1 = Context::New();
context1->Enter();
v8::Handle<v8::Object> global1 = context1->Global();
global1->Set(v8_str("other"), global0);
global1->Set(v8_str("object"), obj_template->NewInstance());
v8::Handle<Value> value;
// Attempt to get the property names of the other global object and
// of an object that requires access checks. Accessing the other
// global object should be blocked by access checks on the global
// proxy object. Accessing the object that requires access checks
// is blocked by the access checks on the object itself.
value = CompileRun("Object.getOwnPropertyNames(other).length == 0");
CHECK(value->IsTrue());
value = CompileRun("Object.getOwnPropertyNames(object).length == 0");
CHECK(value->IsTrue());
context1->Exit();
context0->Exit();
context1.Dispose();
context0.Dispose();
}
static v8::Handle<Value> ConstTenGetter(Local<String> name,
const AccessorInfo& info) {
return v8_num(10);