Commit 92022c11 authored by verwaest@chromium.org's avatar verwaest@chromium.org

Clean up (Get|Set)Property(Attributes)WithFailedAccessChecks

BUG=
R=ishell@chromium.org

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

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@21595 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent dae3413c
...@@ -540,62 +540,43 @@ MaybeHandle<Object> Object::SetPropertyWithDefinedSetter( ...@@ -540,62 +540,43 @@ MaybeHandle<Object> Object::SetPropertyWithDefinedSetter(
} }
// Only deal with CALLBACKS and INTERCEPTOR static bool FindAllCanReadHolder(LookupResult* result,
Handle<Name> name,
bool check_prototype) {
if (result->IsInterceptor()) {
result->holder()->LookupOwnRealNamedProperty(name, result);
}
while (result->IsProperty()) {
if (result->type() == CALLBACKS) {
Object* callback_obj = result->GetCallbackObject();
if (callback_obj->IsAccessorInfo()) {
if (AccessorInfo::cast(callback_obj)->all_can_read()) return true;
} else if (callback_obj->IsAccessorPair()) {
if (AccessorPair::cast(callback_obj)->all_can_read()) return true;
}
}
if (!check_prototype) break;
result->holder()->LookupRealNamedPropertyInPrototypes(name, result);
}
return false;
}
MaybeHandle<Object> JSObject::GetPropertyWithFailedAccessCheck( MaybeHandle<Object> JSObject::GetPropertyWithFailedAccessCheck(
Handle<JSObject> object, Handle<JSObject> object,
Handle<Object> receiver, Handle<Object> receiver,
LookupResult* result, LookupResult* result,
Handle<Name> name, Handle<Name> name,
PropertyAttributes* attributes) { PropertyAttributes* attributes) {
Isolate* isolate = name->GetIsolate(); if (FindAllCanReadHolder(result, name, true)) {
if (result->IsProperty()) { *attributes = result->GetAttributes();
switch (result->type()) { Handle<JSObject> holder(result->holder());
case CALLBACKS: { Handle<Object> callbacks(result->GetCallbackObject(), result->isolate());
// Only allow API accessors. return GetPropertyWithCallback(receiver, name, holder, callbacks);
Handle<Object> callback_obj(result->GetCallbackObject(), isolate);
if (callback_obj->IsAccessorInfo()) {
if (!AccessorInfo::cast(*callback_obj)->all_can_read()) break;
*attributes = result->GetAttributes();
// Fall through to GetPropertyWithCallback.
} else if (callback_obj->IsAccessorPair()) {
if (!AccessorPair::cast(*callback_obj)->all_can_read()) break;
// Fall through to GetPropertyWithCallback.
} else {
break;
}
Handle<JSObject> holder(result->holder(), isolate);
return GetPropertyWithCallback(receiver, name, holder, callback_obj);
}
case NORMAL:
case FIELD:
case CONSTANT: {
// Search ALL_CAN_READ accessors in prototype chain.
LookupResult r(isolate);
result->holder()->LookupRealNamedPropertyInPrototypes(name, &r);
if (r.IsProperty()) {
return GetPropertyWithFailedAccessCheck(
object, receiver, &r, name, attributes);
}
break;
}
case INTERCEPTOR: {
// If the object has an interceptor, try real named properties.
// No access check in GetPropertyAttributeWithInterceptor.
LookupResult r(isolate);
result->holder()->LookupRealNamedProperty(name, &r);
if (r.IsProperty()) {
return GetPropertyWithFailedAccessCheck(
object, receiver, &r, name, attributes);
}
break;
}
default:
UNREACHABLE();
}
} }
// No accessible property found.
*attributes = ABSENT; *attributes = ABSENT;
Isolate* isolate = result->isolate();
isolate->ReportFailedAccessCheck(object, v8::ACCESS_GET); isolate->ReportFailedAccessCheck(object, v8::ACCESS_GET);
RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
return isolate->factory()->undefined_value(); return isolate->factory()->undefined_value();
...@@ -606,63 +587,61 @@ PropertyAttributes JSObject::GetPropertyAttributeWithFailedAccessCheck( ...@@ -606,63 +587,61 @@ PropertyAttributes JSObject::GetPropertyAttributeWithFailedAccessCheck(
Handle<JSObject> object, Handle<JSObject> object,
LookupResult* result, LookupResult* result,
Handle<Name> name, Handle<Name> name,
bool continue_search) { bool check_prototype) {
if (result->IsProperty()) { if (FindAllCanReadHolder(result, name, check_prototype)) {
switch (result->type()) { return result->GetAttributes();
case CALLBACKS: { }
// Only allow API accessors. result->isolate()->ReportFailedAccessCheck(object, v8::ACCESS_HAS);
Handle<Object> obj(result->GetCallbackObject(), object->GetIsolate()); // TODO(yangguo): Issue 3269, check for scheduled exception missing?
if (obj->IsAccessorInfo()) { return ABSENT;
Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(obj); }
if (info->all_can_read()) {
return result->GetAttributes();
}
} else if (obj->IsAccessorPair()) {
Handle<AccessorPair> pair = Handle<AccessorPair>::cast(obj);
if (pair->all_can_read()) {
return result->GetAttributes();
}
}
break;
}
case NORMAL:
case FIELD:
case CONSTANT: {
if (!continue_search) break;
// Search ALL_CAN_READ accessors in prototype chain.
LookupResult r(object->GetIsolate());
result->holder()->LookupRealNamedPropertyInPrototypes(name, &r);
if (r.IsProperty()) {
return GetPropertyAttributeWithFailedAccessCheck(
object, &r, name, continue_search);
}
break;
}
case INTERCEPTOR: { static bool FindAllCanWriteHolder(LookupResult* result,
// If the object has an interceptor, try real named properties. Handle<Name> name,
// No access check in GetPropertyAttributeWithInterceptor. bool check_prototype) {
LookupResult r(object->GetIsolate()); if (result->IsInterceptor()) {
if (continue_search) { result->holder()->LookupOwnRealNamedProperty(name, result);
result->holder()->LookupRealNamedProperty(name, &r); }
} else {
result->holder()->LookupOwnRealNamedProperty(name, &r); while (result->IsProperty()) {
} if (result->type() == CALLBACKS) {
if (!r.IsFound()) break; Object* callback_obj = result->GetCallbackObject();
return GetPropertyAttributeWithFailedAccessCheck( if (callback_obj->IsAccessorInfo()) {
object, &r, name, continue_search); if (AccessorInfo::cast(callback_obj)->all_can_write()) return true;
} else if (callback_obj->IsAccessorPair()) {
if (AccessorPair::cast(callback_obj)->all_can_write()) return true;
} }
case HANDLER:
case NONEXISTENT:
UNREACHABLE();
} }
if (!check_prototype) break;
result->holder()->LookupRealNamedPropertyInPrototypes(name, result);
} }
return false;
}
object->GetIsolate()->ReportFailedAccessCheck(object, v8::ACCESS_HAS);
// TODO(yangguo): Issue 3269, check for scheduled exception missing? MaybeHandle<Object> JSObject::SetPropertyWithFailedAccessCheck(
return ABSENT; Handle<JSObject> object,
LookupResult* result,
Handle<Name> name,
Handle<Object> value,
bool check_prototype,
StrictMode strict_mode) {
if (check_prototype && !result->IsProperty()) {
object->LookupRealNamedPropertyInPrototypes(name, result);
}
if (FindAllCanWriteHolder(result, name, check_prototype)) {
Handle<JSObject> holder(result->holder());
Handle<Object> callbacks(result->GetCallbackObject(), result->isolate());
return SetPropertyWithCallback(
object, name, value, holder, callbacks, strict_mode);
}
Isolate* isolate = object->GetIsolate();
isolate->ReportFailedAccessCheck(object, v8::ACCESS_SET);
RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
return value;
} }
...@@ -834,11 +813,11 @@ MaybeHandle<Object> Object::GetProperty(Handle<Object> object, ...@@ -834,11 +813,11 @@ MaybeHandle<Object> Object::GetProperty(Handle<Object> object,
if (!result->IsHandler()) { if (!result->IsHandler()) {
ASSERT(*object != object->GetPrototype(isolate)); ASSERT(*object != object->GetPrototype(isolate));
Handle<Object> last = result->IsProperty() Handle<Object> last = result->IsProperty()
? Handle<Object>(result->holder(), isolate) ? handle(result->holder()->GetPrototype(), isolate)
: Handle<Object>::cast(factory->null_value()); : Handle<Object>::cast(factory->null_value());
for (Handle<Object> current = object; for (Handle<Object> current = object;
true; !current.is_identical_to(last);
current = Handle<Object>(current->GetPrototype(isolate), isolate)) { current = Object::GetPrototype(isolate, current)) {
if (current->IsAccessCheckNeeded()) { if (current->IsAccessCheckNeeded()) {
// Check if we're allowed to read from the current object. Note // Check if we're allowed to read from the current object. Note
// that even though we may not actually end up loading the named // that even though we may not actually end up loading the named
...@@ -850,10 +829,6 @@ MaybeHandle<Object> Object::GetProperty(Handle<Object> object, ...@@ -850,10 +829,6 @@ MaybeHandle<Object> Object::GetProperty(Handle<Object> object,
checked, receiver, result, name, attributes); checked, receiver, result, name, attributes);
} }
} }
// Stop traversing the chain once we reach the last object in the
// chain; either the holder of the result or null in case of an
// absent property.
if (current.is_identical_to(last)) break;
} }
} }
...@@ -3603,69 +3578,6 @@ void JSObject::LookupRealNamedPropertyInPrototypes(Handle<Name> name, ...@@ -3603,69 +3578,6 @@ void JSObject::LookupRealNamedPropertyInPrototypes(Handle<Name> name,
} }
// We only need to deal with CALLBACKS and INTERCEPTORS
MaybeHandle<Object> JSObject::SetPropertyWithFailedAccessCheck(
Handle<JSObject> object,
LookupResult* result,
Handle<Name> name,
Handle<Object> value,
bool check_prototype,
StrictMode strict_mode) {
if (check_prototype && !result->IsProperty()) {
object->LookupRealNamedPropertyInPrototypes(name, result);
}
if (result->IsProperty()) {
if (!result->IsReadOnly()) {
switch (result->type()) {
case CALLBACKS: {
Object* obj = result->GetCallbackObject();
if (obj->IsAccessorInfo()) {
Handle<AccessorInfo> info(AccessorInfo::cast(obj));
if (info->all_can_write()) {
return SetPropertyWithCallback(object, name, value,
handle(result->holder()),
info, strict_mode);
}
} else if (obj->IsAccessorPair()) {
Handle<AccessorPair> pair(AccessorPair::cast(obj));
if (pair->all_can_read()) {
return SetPropertyWithCallback(object, name, value,
handle(result->holder()),
pair, strict_mode);
}
}
break;
}
case INTERCEPTOR: {
// Try lookup real named properties. Note that only property can be
// set is callbacks marked as ALL_CAN_WRITE on the prototype chain.
LookupResult r(object->GetIsolate());
object->LookupRealNamedProperty(name, &r);
if (r.IsProperty()) {
return SetPropertyWithFailedAccessCheck(object,
&r,
name,
value,
check_prototype,
strict_mode);
}
break;
}
default: {
break;
}
}
}
}
Isolate* isolate = object->GetIsolate();
isolate->ReportFailedAccessCheck(object, v8::ACCESS_SET);
RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
return value;
}
MaybeHandle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object, MaybeHandle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object,
LookupResult* result, LookupResult* result,
Handle<Name> key, Handle<Name> key,
...@@ -4505,14 +4417,14 @@ PropertyAttributes JSObject::GetPropertyAttributePostInterceptor( ...@@ -4505,14 +4417,14 @@ PropertyAttributes JSObject::GetPropertyAttributePostInterceptor(
Handle<JSObject> object, Handle<JSObject> object,
Handle<JSObject> receiver, Handle<JSObject> receiver,
Handle<Name> name, Handle<Name> name,
bool continue_search) { bool check_prototype) {
// Check own property, ignore interceptor. // Check own property, ignore interceptor.
Isolate* isolate = object->GetIsolate(); Isolate* isolate = object->GetIsolate();
LookupResult result(isolate); LookupResult result(isolate);
object->LookupOwnRealNamedProperty(name, &result); object->LookupOwnRealNamedProperty(name, &result);
if (result.IsFound()) return result.GetAttributes(); if (result.IsFound()) return result.GetAttributes();
if (continue_search) { if (check_prototype) {
// Continue searching via the prototype chain. // Continue searching via the prototype chain.
Handle<Object> proto(object->GetPrototype(), isolate); Handle<Object> proto(object->GetPrototype(), isolate);
if (!proto->IsNull()) { if (!proto->IsNull()) {
...@@ -4528,7 +4440,7 @@ PropertyAttributes JSObject::GetPropertyAttributeWithInterceptor( ...@@ -4528,7 +4440,7 @@ PropertyAttributes JSObject::GetPropertyAttributeWithInterceptor(
Handle<JSObject> object, Handle<JSObject> object,
Handle<JSObject> receiver, Handle<JSObject> receiver,
Handle<Name> name, Handle<Name> name,
bool continue_search) { bool check_prototype) {
// TODO(rossberg): Support symbols in the API. // TODO(rossberg): Support symbols in the API.
if (name->IsSymbol()) return ABSENT; if (name->IsSymbol()) return ABSENT;
...@@ -4563,7 +4475,7 @@ PropertyAttributes JSObject::GetPropertyAttributeWithInterceptor( ...@@ -4563,7 +4475,7 @@ PropertyAttributes JSObject::GetPropertyAttributeWithInterceptor(
if (!result.IsEmpty()) return DONT_ENUM; if (!result.IsEmpty()) return DONT_ENUM;
} }
return GetPropertyAttributePostInterceptor( return GetPropertyAttributePostInterceptor(
object, receiver, name, continue_search); object, receiver, name, check_prototype);
} }
...@@ -4588,14 +4500,14 @@ PropertyAttributes JSReceiver::GetPropertyAttributeForResult( ...@@ -4588,14 +4500,14 @@ PropertyAttributes JSReceiver::GetPropertyAttributeForResult(
Handle<JSReceiver> receiver, Handle<JSReceiver> receiver,
LookupResult* lookup, LookupResult* lookup,
Handle<Name> name, Handle<Name> name,
bool continue_search) { bool check_prototype) {
// Check access rights if needed. // Check access rights if needed.
if (object->IsAccessCheckNeeded()) { if (object->IsAccessCheckNeeded()) {
Heap* heap = object->GetHeap(); Heap* heap = object->GetHeap();
Handle<JSObject> obj = Handle<JSObject>::cast(object); Handle<JSObject> obj = Handle<JSObject>::cast(object);
if (!heap->isolate()->MayNamedAccess(obj, name, v8::ACCESS_HAS)) { if (!heap->isolate()->MayNamedAccess(obj, name, v8::ACCESS_HAS)) {
return JSObject::GetPropertyAttributeWithFailedAccessCheck( return JSObject::GetPropertyAttributeWithFailedAccessCheck(
obj, lookup, name, continue_search); obj, lookup, name, check_prototype);
} }
} }
if (lookup->IsFound()) { if (lookup->IsFound()) {
...@@ -4614,7 +4526,7 @@ PropertyAttributes JSReceiver::GetPropertyAttributeForResult( ...@@ -4614,7 +4526,7 @@ PropertyAttributes JSReceiver::GetPropertyAttributeForResult(
handle(lookup->holder()), handle(lookup->holder()),
Handle<JSObject>::cast(receiver), Handle<JSObject>::cast(receiver),
name, name,
continue_search); check_prototype);
case NONEXISTENT: case NONEXISTENT:
UNREACHABLE(); UNREACHABLE();
} }
...@@ -4641,7 +4553,7 @@ PropertyAttributes JSObject::GetElementAttributeWithReceiver( ...@@ -4641,7 +4553,7 @@ PropertyAttributes JSObject::GetElementAttributeWithReceiver(
Handle<JSObject> object, Handle<JSObject> object,
Handle<JSReceiver> receiver, Handle<JSReceiver> receiver,
uint32_t index, uint32_t index,
bool continue_search) { bool check_prototype) {
Isolate* isolate = object->GetIsolate(); Isolate* isolate = object->GetIsolate();
// Check access rights if needed. // Check access rights if needed.
...@@ -4658,17 +4570,17 @@ PropertyAttributes JSObject::GetElementAttributeWithReceiver( ...@@ -4658,17 +4570,17 @@ PropertyAttributes JSObject::GetElementAttributeWithReceiver(
if (proto->IsNull()) return ABSENT; if (proto->IsNull()) return ABSENT;
ASSERT(proto->IsJSGlobalObject()); ASSERT(proto->IsJSGlobalObject());
return JSObject::GetElementAttributeWithReceiver( return JSObject::GetElementAttributeWithReceiver(
Handle<JSObject>::cast(proto), receiver, index, continue_search); Handle<JSObject>::cast(proto), receiver, index, check_prototype);
} }
// Check for lookup interceptor except when bootstrapping. // Check for lookup interceptor except when bootstrapping.
if (object->HasIndexedInterceptor() && !isolate->bootstrapper()->IsActive()) { if (object->HasIndexedInterceptor() && !isolate->bootstrapper()->IsActive()) {
return JSObject::GetElementAttributeWithInterceptor( return JSObject::GetElementAttributeWithInterceptor(
object, receiver, index, continue_search); object, receiver, index, check_prototype);
} }
return GetElementAttributeWithoutInterceptor( return GetElementAttributeWithoutInterceptor(
object, receiver, index, continue_search); object, receiver, index, check_prototype);
} }
...@@ -4676,7 +4588,7 @@ PropertyAttributes JSObject::GetElementAttributeWithInterceptor( ...@@ -4676,7 +4588,7 @@ PropertyAttributes JSObject::GetElementAttributeWithInterceptor(
Handle<JSObject> object, Handle<JSObject> object,
Handle<JSReceiver> receiver, Handle<JSReceiver> receiver,
uint32_t index, uint32_t index,
bool continue_search) { bool check_prototype) {
Isolate* isolate = object->GetIsolate(); Isolate* isolate = object->GetIsolate();
HandleScope scope(isolate); HandleScope scope(isolate);
...@@ -4706,7 +4618,7 @@ PropertyAttributes JSObject::GetElementAttributeWithInterceptor( ...@@ -4706,7 +4618,7 @@ PropertyAttributes JSObject::GetElementAttributeWithInterceptor(
} }
return GetElementAttributeWithoutInterceptor( return GetElementAttributeWithoutInterceptor(
object, receiver, index, continue_search); object, receiver, index, check_prototype);
} }
...@@ -4714,7 +4626,7 @@ PropertyAttributes JSObject::GetElementAttributeWithoutInterceptor( ...@@ -4714,7 +4626,7 @@ PropertyAttributes JSObject::GetElementAttributeWithoutInterceptor(
Handle<JSObject> object, Handle<JSObject> object,
Handle<JSReceiver> receiver, Handle<JSReceiver> receiver,
uint32_t index, uint32_t index,
bool continue_search) { bool check_prototype) {
PropertyAttributes attr = object->GetElementsAccessor()->GetAttributes( PropertyAttributes attr = object->GetElementsAccessor()->GetAttributes(
receiver, object, index); receiver, object, index);
if (attr != ABSENT) return attr; if (attr != ABSENT) return attr;
...@@ -4724,7 +4636,7 @@ PropertyAttributes JSObject::GetElementAttributeWithoutInterceptor( ...@@ -4724,7 +4636,7 @@ PropertyAttributes JSObject::GetElementAttributeWithoutInterceptor(
return static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE); return static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE);
} }
if (!continue_search) return ABSENT; if (!check_prototype) return ABSENT;
Handle<Object> proto(object->GetPrototype(), object->GetIsolate()); Handle<Object> proto(object->GetPrototype(), object->GetIsolate());
if (proto->IsJSProxy()) { if (proto->IsJSProxy()) {
......
...@@ -2222,22 +2222,22 @@ class JSObject: public JSReceiver { ...@@ -2222,22 +2222,22 @@ class JSObject: public JSReceiver {
Handle<JSObject> object, Handle<JSObject> object,
Handle<JSObject> receiver, Handle<JSObject> receiver,
Handle<Name> name, Handle<Name> name,
bool continue_search); bool check_prototype);
static PropertyAttributes GetPropertyAttributeWithInterceptor( static PropertyAttributes GetPropertyAttributeWithInterceptor(
Handle<JSObject> object, Handle<JSObject> object,
Handle<JSObject> receiver, Handle<JSObject> receiver,
Handle<Name> name, Handle<Name> name,
bool continue_search); bool check_prototype);
static PropertyAttributes GetPropertyAttributeWithFailedAccessCheck( static PropertyAttributes GetPropertyAttributeWithFailedAccessCheck(
Handle<JSObject> object, Handle<JSObject> object,
LookupResult* result, LookupResult* result,
Handle<Name> name, Handle<Name> name,
bool continue_search); bool check_prototype);
static PropertyAttributes GetElementAttributeWithReceiver( static PropertyAttributes GetElementAttributeWithReceiver(
Handle<JSObject> object, Handle<JSObject> object,
Handle<JSReceiver> receiver, Handle<JSReceiver> receiver,
uint32_t index, uint32_t index,
bool continue_search); bool check_prototype);
// Retrieves an AccessorPair property from the given object. Might return // Retrieves an AccessorPair property from the given object. Might return
// undefined if the property doesn't exist or is of a different kind. // undefined if the property doesn't exist or is of a different kind.
......
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