| Index: src/runtime.cc
|
| diff --git a/src/runtime.cc b/src/runtime.cc
|
| index 927386289ac392254281077665c980768294f946..f149ebfe39d863426d6255ebb678b7cc21df80a2 100644
|
| --- a/src/runtime.cc
|
| +++ b/src/runtime.cc
|
| @@ -1914,83 +1914,64 @@ static bool CheckAccessException(Object* callback,
|
| template<class Key>
|
| static bool CheckGenericAccess(
|
| Handle<JSObject> receiver,
|
| - Handle<JSObject> holder,
|
| + Handle<Object> end,
|
| Key key,
|
| v8::AccessType access_type,
|
| bool (Isolate::*mayAccess)(Handle<JSObject>, Key, v8::AccessType)) {
|
| Isolate* isolate = receiver->GetIsolate();
|
| - for (Handle<JSObject> current = receiver;
|
| - true;
|
| - current = handle(JSObject::cast(current->GetPrototype()), isolate)) {
|
| + for (Handle<Object> current = receiver;
|
| + !current.is_identical_to(end);
|
| + current = Object::GetPrototype(isolate, current)) {
|
| if (current->IsAccessCheckNeeded() &&
|
| - !(isolate->*mayAccess)(current, key, access_type)) {
|
| + !(isolate->*mayAccess)(
|
| + Handle<JSObject>::cast(current), key, access_type)) {
|
| return false;
|
| }
|
| - if (current.is_identical_to(holder)) break;
|
| }
|
| return true;
|
| }
|
|
|
|
|
| -enum AccessCheckResult {
|
| - ACCESS_FORBIDDEN,
|
| - ACCESS_ALLOWED,
|
| - ACCESS_ABSENT
|
| -};
|
| -
|
| -
|
| -static AccessCheckResult CheckPropertyAccess(Handle<JSObject> obj,
|
| - Handle<Name> name,
|
| - v8::AccessType access_type) {
|
| +static void CheckPropertyAccess(Handle<JSObject> obj,
|
| + Handle<Name> name,
|
| + v8::AccessType access_type) {
|
| + Isolate* isolate = obj->GetIsolate();
|
| uint32_t index;
|
| if (name->AsArrayIndex(&index)) {
|
| + Handle<Object> next(obj->GetPrototype(), isolate);
|
| // TODO(1095): we should traverse hidden prototype hierachy as well.
|
| - if (CheckGenericAccess(
|
| - obj, obj, index, access_type, &Isolate::MayIndexedAccess)) {
|
| - return ACCESS_ALLOWED;
|
| + if (!CheckGenericAccess(
|
| + obj, next, index, access_type, &Isolate::MayIndexedAccess)) {
|
| + obj->GetIsolate()->ReportFailedAccessCheck(obj, access_type);
|
| }
|
| -
|
| - obj->GetIsolate()->ReportFailedAccessCheck(obj, access_type);
|
| - return ACCESS_FORBIDDEN;
|
| + return;
|
| }
|
|
|
| - Isolate* isolate = obj->GetIsolate();
|
| LookupResult lookup(isolate);
|
| obj->LookupOwn(name, &lookup, true);
|
|
|
| - if (!lookup.IsProperty()) return ACCESS_ABSENT;
|
| - Handle<JSObject> holder(lookup.holder(), isolate);
|
| + Handle<Object> next = lookup.IsProperty()
|
| + ? handle(lookup.holder()->GetPrototype(), isolate)
|
| + : Handle<Object>::cast(isolate->factory()->null_value());
|
| if (CheckGenericAccess<Handle<Object> >(
|
| - obj, holder, name, access_type, &Isolate::MayNamedAccess)) {
|
| - return ACCESS_ALLOWED;
|
| + obj, next, name, access_type, &Isolate::MayNamedAccess)) {
|
| + return;
|
| }
|
|
|
| // Access check callback denied the access, but some properties
|
| // can have a special permissions which override callbacks descision
|
| // (currently see v8::AccessControl).
|
| // API callbacks can have per callback access exceptions.
|
| - switch (lookup.type()) {
|
| - case CALLBACKS:
|
| - if (CheckAccessException(lookup.GetCallbackObject(), access_type)) {
|
| - return ACCESS_ALLOWED;
|
| - }
|
| - break;
|
| - case INTERCEPTOR:
|
| - // If the object has an interceptor, try real named properties.
|
| - // Overwrite the result to fetch the correct property later.
|
| - holder->LookupRealNamedProperty(name, &lookup);
|
| - if (lookup.IsProperty() && lookup.IsPropertyCallbacks()) {
|
| - if (CheckAccessException(lookup.GetCallbackObject(), access_type)) {
|
| - return ACCESS_ALLOWED;
|
| - }
|
| - }
|
| - break;
|
| - default:
|
| - break;
|
| + if (lookup.IsFound() && lookup.type() == INTERCEPTOR) {
|
| + lookup.holder()->LookupOwnRealNamedProperty(name, &lookup);
|
| + }
|
| +
|
| + if (lookup.IsPropertyCallbacks() &&
|
| + CheckAccessException(lookup.GetCallbackObject(), access_type)) {
|
| + return;
|
| }
|
|
|
| isolate->ReportFailedAccessCheck(obj, access_type);
|
| - return ACCESS_FORBIDDEN;
|
| }
|
|
|
|
|
| @@ -2012,16 +1993,9 @@ MUST_USE_RESULT static MaybeHandle<Object> GetOwnProperty(Isolate* isolate,
|
| Handle<Name> name) {
|
| Heap* heap = isolate->heap();
|
| Factory* factory = isolate->factory();
|
| - // Due to some WebKit tests, we want to make sure that we do not log
|
| - // more than one access failure here.
|
| - AccessCheckResult access_check_result =
|
| - CheckPropertyAccess(obj, name, v8::ACCESS_HAS);
|
| +
|
| + CheckPropertyAccess(obj, name, v8::ACCESS_HAS);
|
| RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
|
| - switch (access_check_result) {
|
| - case ACCESS_FORBIDDEN: return factory->false_value();
|
| - case ACCESS_ALLOWED: break;
|
| - case ACCESS_ABSENT: return factory->undefined_value();
|
| - }
|
|
|
| PropertyAttributes attrs = JSReceiver::GetOwnPropertyAttributes(obj, name);
|
| if (attrs == ABSENT) {
|
| @@ -2032,7 +2006,7 @@ MUST_USE_RESULT static MaybeHandle<Object> GetOwnProperty(Isolate* isolate,
|
| Handle<AccessorPair> accessors;
|
| bool has_accessors =
|
| JSObject::GetOwnPropertyAccessorPair(obj, name).ToHandle(&accessors);
|
| - Handle<FixedArray> elms = isolate->factory()->NewFixedArray(DESCRIPTOR_SIZE);
|
| + Handle<FixedArray> elms = factory->NewFixedArray(DESCRIPTOR_SIZE);
|
| elms->set(ENUMERABLE_INDEX, heap->ToBoolean((attrs & DONT_ENUM) == 0));
|
| elms->set(CONFIGURABLE_INDEX, heap->ToBoolean((attrs & DONT_DELETE) == 0));
|
| elms->set(IS_ACCESSOR_INDEX, heap->ToBoolean(has_accessors));
|
| @@ -2046,27 +2020,13 @@ MUST_USE_RESULT static MaybeHandle<Object> GetOwnProperty(Isolate* isolate,
|
| Object);
|
| elms->set(VALUE_INDEX, *value);
|
| } else {
|
| - // Access checks are performed for both accessors separately.
|
| - // When they fail, the respective field is not set in the descriptor.
|
| Handle<Object> getter(accessors->GetComponent(ACCESSOR_GETTER), isolate);
|
| Handle<Object> setter(accessors->GetComponent(ACCESSOR_SETTER), isolate);
|
| -
|
| - if (!getter->IsMap() && CheckPropertyAccess(obj, name, v8::ACCESS_GET)) {
|
| - ASSERT(!isolate->has_scheduled_exception());
|
| - elms->set(GETTER_INDEX, *getter);
|
| - } else {
|
| - RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
|
| - }
|
| -
|
| - if (!setter->IsMap() && CheckPropertyAccess(obj, name, v8::ACCESS_SET)) {
|
| - ASSERT(!isolate->has_scheduled_exception());
|
| - elms->set(SETTER_INDEX, *setter);
|
| - } else {
|
| - RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
|
| - }
|
| + elms->set(GETTER_INDEX, *getter);
|
| + elms->set(SETTER_INDEX, *setter);
|
| }
|
|
|
| - return isolate->factory()->NewJSArrayWithElements(elms);
|
| + return factory->NewJSArrayWithElements(elms);
|
| }
|
|
|
|
|
|
|