OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <stdlib.h> | 5 #include <stdlib.h> |
6 #include <limits> | 6 #include <limits> |
7 | 7 |
8 #include "src/v8.h" | 8 #include "src/v8.h" |
9 | 9 |
10 #include "src/accessors.h" | 10 #include "src/accessors.h" |
(...skipping 1896 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1907 (access_type == v8::ACCESS_GET && info->all_can_read()) || | 1907 (access_type == v8::ACCESS_GET && info->all_can_read()) || |
1908 (access_type == v8::ACCESS_SET && info->all_can_write()); | 1908 (access_type == v8::ACCESS_SET && info->all_can_write()); |
1909 } | 1909 } |
1910 return false; | 1910 return false; |
1911 } | 1911 } |
1912 | 1912 |
1913 | 1913 |
1914 template<class Key> | 1914 template<class Key> |
1915 static bool CheckGenericAccess( | 1915 static bool CheckGenericAccess( |
1916 Handle<JSObject> receiver, | 1916 Handle<JSObject> receiver, |
1917 Handle<JSObject> holder, | 1917 Handle<Object> end, |
1918 Key key, | 1918 Key key, |
1919 v8::AccessType access_type, | 1919 v8::AccessType access_type, |
1920 bool (Isolate::*mayAccess)(Handle<JSObject>, Key, v8::AccessType)) { | 1920 bool (Isolate::*mayAccess)(Handle<JSObject>, Key, v8::AccessType)) { |
1921 Isolate* isolate = receiver->GetIsolate(); | 1921 Isolate* isolate = receiver->GetIsolate(); |
1922 for (Handle<JSObject> current = receiver; | 1922 for (Handle<Object> current = receiver; |
1923 true; | 1923 !current.is_identical_to(end); |
1924 current = handle(JSObject::cast(current->GetPrototype()), isolate)) { | 1924 current = Object::GetPrototype(isolate, current)) { |
1925 if (current->IsAccessCheckNeeded() && | 1925 if (current->IsAccessCheckNeeded() && |
1926 !(isolate->*mayAccess)(current, key, access_type)) { | 1926 !(isolate->*mayAccess)( |
| 1927 Handle<JSObject>::cast(current), key, access_type)) { |
1927 return false; | 1928 return false; |
1928 } | 1929 } |
1929 if (current.is_identical_to(holder)) break; | |
1930 } | 1930 } |
1931 return true; | 1931 return true; |
1932 } | 1932 } |
1933 | 1933 |
1934 | 1934 |
1935 enum AccessCheckResult { | 1935 static void CheckPropertyAccess(Handle<JSObject> obj, |
1936 ACCESS_FORBIDDEN, | 1936 Handle<Name> name, |
1937 ACCESS_ALLOWED, | 1937 v8::AccessType access_type) { |
1938 ACCESS_ABSENT | 1938 Isolate* isolate = obj->GetIsolate(); |
1939 }; | |
1940 | |
1941 | |
1942 static AccessCheckResult CheckPropertyAccess(Handle<JSObject> obj, | |
1943 Handle<Name> name, | |
1944 v8::AccessType access_type) { | |
1945 uint32_t index; | 1939 uint32_t index; |
1946 if (name->AsArrayIndex(&index)) { | 1940 if (name->AsArrayIndex(&index)) { |
| 1941 Handle<Object> next(obj->GetPrototype(), isolate); |
1947 // TODO(1095): we should traverse hidden prototype hierachy as well. | 1942 // TODO(1095): we should traverse hidden prototype hierachy as well. |
1948 if (CheckGenericAccess( | 1943 if (!CheckGenericAccess( |
1949 obj, obj, index, access_type, &Isolate::MayIndexedAccess)) { | 1944 obj, next, index, access_type, &Isolate::MayIndexedAccess)) { |
1950 return ACCESS_ALLOWED; | 1945 obj->GetIsolate()->ReportFailedAccessCheck(obj, access_type); |
1951 } | 1946 } |
1952 | 1947 return; |
1953 obj->GetIsolate()->ReportFailedAccessCheck(obj, access_type); | |
1954 return ACCESS_FORBIDDEN; | |
1955 } | 1948 } |
1956 | 1949 |
1957 Isolate* isolate = obj->GetIsolate(); | |
1958 LookupResult lookup(isolate); | 1950 LookupResult lookup(isolate); |
1959 obj->LookupOwn(name, &lookup, true); | 1951 obj->LookupOwn(name, &lookup, true); |
1960 | 1952 |
1961 if (!lookup.IsProperty()) return ACCESS_ABSENT; | 1953 Handle<Object> next = lookup.IsProperty() |
1962 Handle<JSObject> holder(lookup.holder(), isolate); | 1954 ? handle(lookup.holder()->GetPrototype(), isolate) |
| 1955 : Handle<Object>::cast(isolate->factory()->null_value()); |
1963 if (CheckGenericAccess<Handle<Object> >( | 1956 if (CheckGenericAccess<Handle<Object> >( |
1964 obj, holder, name, access_type, &Isolate::MayNamedAccess)) { | 1957 obj, next, name, access_type, &Isolate::MayNamedAccess)) { |
1965 return ACCESS_ALLOWED; | 1958 return; |
1966 } | 1959 } |
1967 | 1960 |
1968 // Access check callback denied the access, but some properties | 1961 // Access check callback denied the access, but some properties |
1969 // can have a special permissions which override callbacks descision | 1962 // can have a special permissions which override callbacks descision |
1970 // (currently see v8::AccessControl). | 1963 // (currently see v8::AccessControl). |
1971 // API callbacks can have per callback access exceptions. | 1964 // API callbacks can have per callback access exceptions. |
1972 switch (lookup.type()) { | 1965 if (lookup.IsFound() && lookup.type() == INTERCEPTOR) { |
1973 case CALLBACKS: | 1966 lookup.holder()->LookupOwnRealNamedProperty(name, &lookup); |
1974 if (CheckAccessException(lookup.GetCallbackObject(), access_type)) { | 1967 } |
1975 return ACCESS_ALLOWED; | 1968 |
1976 } | 1969 if (lookup.IsPropertyCallbacks() && |
1977 break; | 1970 CheckAccessException(lookup.GetCallbackObject(), access_type)) { |
1978 case INTERCEPTOR: | 1971 return; |
1979 // If the object has an interceptor, try real named properties. | |
1980 // Overwrite the result to fetch the correct property later. | |
1981 holder->LookupRealNamedProperty(name, &lookup); | |
1982 if (lookup.IsProperty() && lookup.IsPropertyCallbacks()) { | |
1983 if (CheckAccessException(lookup.GetCallbackObject(), access_type)) { | |
1984 return ACCESS_ALLOWED; | |
1985 } | |
1986 } | |
1987 break; | |
1988 default: | |
1989 break; | |
1990 } | 1972 } |
1991 | 1973 |
1992 isolate->ReportFailedAccessCheck(obj, access_type); | 1974 isolate->ReportFailedAccessCheck(obj, access_type); |
1993 return ACCESS_FORBIDDEN; | |
1994 } | 1975 } |
1995 | 1976 |
1996 | 1977 |
1997 // Enumerator used as indices into the array returned from GetOwnProperty | 1978 // Enumerator used as indices into the array returned from GetOwnProperty |
1998 enum PropertyDescriptorIndices { | 1979 enum PropertyDescriptorIndices { |
1999 IS_ACCESSOR_INDEX, | 1980 IS_ACCESSOR_INDEX, |
2000 VALUE_INDEX, | 1981 VALUE_INDEX, |
2001 GETTER_INDEX, | 1982 GETTER_INDEX, |
2002 SETTER_INDEX, | 1983 SETTER_INDEX, |
2003 WRITABLE_INDEX, | 1984 WRITABLE_INDEX, |
2004 ENUMERABLE_INDEX, | 1985 ENUMERABLE_INDEX, |
2005 CONFIGURABLE_INDEX, | 1986 CONFIGURABLE_INDEX, |
2006 DESCRIPTOR_SIZE | 1987 DESCRIPTOR_SIZE |
2007 }; | 1988 }; |
2008 | 1989 |
2009 | 1990 |
2010 MUST_USE_RESULT static MaybeHandle<Object> GetOwnProperty(Isolate* isolate, | 1991 MUST_USE_RESULT static MaybeHandle<Object> GetOwnProperty(Isolate* isolate, |
2011 Handle<JSObject> obj, | 1992 Handle<JSObject> obj, |
2012 Handle<Name> name) { | 1993 Handle<Name> name) { |
2013 Heap* heap = isolate->heap(); | 1994 Heap* heap = isolate->heap(); |
2014 Factory* factory = isolate->factory(); | 1995 Factory* factory = isolate->factory(); |
2015 // Due to some WebKit tests, we want to make sure that we do not log | 1996 |
2016 // more than one access failure here. | 1997 CheckPropertyAccess(obj, name, v8::ACCESS_HAS); |
2017 AccessCheckResult access_check_result = | |
2018 CheckPropertyAccess(obj, name, v8::ACCESS_HAS); | |
2019 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | 1998 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); |
2020 switch (access_check_result) { | |
2021 case ACCESS_FORBIDDEN: return factory->false_value(); | |
2022 case ACCESS_ALLOWED: break; | |
2023 case ACCESS_ABSENT: return factory->undefined_value(); | |
2024 } | |
2025 | 1999 |
2026 PropertyAttributes attrs = JSReceiver::GetOwnPropertyAttributes(obj, name); | 2000 PropertyAttributes attrs = JSReceiver::GetOwnPropertyAttributes(obj, name); |
2027 if (attrs == ABSENT) { | 2001 if (attrs == ABSENT) { |
2028 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | 2002 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); |
2029 return factory->undefined_value(); | 2003 return factory->undefined_value(); |
2030 } | 2004 } |
2031 ASSERT(!isolate->has_scheduled_exception()); | 2005 ASSERT(!isolate->has_scheduled_exception()); |
2032 Handle<AccessorPair> accessors; | 2006 Handle<AccessorPair> accessors; |
2033 bool has_accessors = | 2007 bool has_accessors = |
2034 JSObject::GetOwnPropertyAccessorPair(obj, name).ToHandle(&accessors); | 2008 JSObject::GetOwnPropertyAccessorPair(obj, name).ToHandle(&accessors); |
2035 Handle<FixedArray> elms = isolate->factory()->NewFixedArray(DESCRIPTOR_SIZE); | 2009 Handle<FixedArray> elms = factory->NewFixedArray(DESCRIPTOR_SIZE); |
2036 elms->set(ENUMERABLE_INDEX, heap->ToBoolean((attrs & DONT_ENUM) == 0)); | 2010 elms->set(ENUMERABLE_INDEX, heap->ToBoolean((attrs & DONT_ENUM) == 0)); |
2037 elms->set(CONFIGURABLE_INDEX, heap->ToBoolean((attrs & DONT_DELETE) == 0)); | 2011 elms->set(CONFIGURABLE_INDEX, heap->ToBoolean((attrs & DONT_DELETE) == 0)); |
2038 elms->set(IS_ACCESSOR_INDEX, heap->ToBoolean(has_accessors)); | 2012 elms->set(IS_ACCESSOR_INDEX, heap->ToBoolean(has_accessors)); |
2039 | 2013 |
2040 if (!has_accessors) { | 2014 if (!has_accessors) { |
2041 elms->set(WRITABLE_INDEX, heap->ToBoolean((attrs & READ_ONLY) == 0)); | 2015 elms->set(WRITABLE_INDEX, heap->ToBoolean((attrs & READ_ONLY) == 0)); |
2042 // Runtime::GetObjectProperty does access check. | 2016 // Runtime::GetObjectProperty does access check. |
2043 Handle<Object> value; | 2017 Handle<Object> value; |
2044 ASSIGN_RETURN_ON_EXCEPTION( | 2018 ASSIGN_RETURN_ON_EXCEPTION( |
2045 isolate, value, Runtime::GetObjectProperty(isolate, obj, name), | 2019 isolate, value, Runtime::GetObjectProperty(isolate, obj, name), |
2046 Object); | 2020 Object); |
2047 elms->set(VALUE_INDEX, *value); | 2021 elms->set(VALUE_INDEX, *value); |
2048 } else { | 2022 } else { |
2049 // Access checks are performed for both accessors separately. | |
2050 // When they fail, the respective field is not set in the descriptor. | |
2051 Handle<Object> getter(accessors->GetComponent(ACCESSOR_GETTER), isolate); | 2023 Handle<Object> getter(accessors->GetComponent(ACCESSOR_GETTER), isolate); |
2052 Handle<Object> setter(accessors->GetComponent(ACCESSOR_SETTER), isolate); | 2024 Handle<Object> setter(accessors->GetComponent(ACCESSOR_SETTER), isolate); |
2053 | 2025 elms->set(GETTER_INDEX, *getter); |
2054 if (!getter->IsMap() && CheckPropertyAccess(obj, name, v8::ACCESS_GET)) { | 2026 elms->set(SETTER_INDEX, *setter); |
2055 ASSERT(!isolate->has_scheduled_exception()); | |
2056 elms->set(GETTER_INDEX, *getter); | |
2057 } else { | |
2058 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | |
2059 } | |
2060 | |
2061 if (!setter->IsMap() && CheckPropertyAccess(obj, name, v8::ACCESS_SET)) { | |
2062 ASSERT(!isolate->has_scheduled_exception()); | |
2063 elms->set(SETTER_INDEX, *setter); | |
2064 } else { | |
2065 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | |
2066 } | |
2067 } | 2027 } |
2068 | 2028 |
2069 return isolate->factory()->NewJSArrayWithElements(elms); | 2029 return factory->NewJSArrayWithElements(elms); |
2070 } | 2030 } |
2071 | 2031 |
2072 | 2032 |
2073 // Returns an array with the property description: | 2033 // Returns an array with the property description: |
2074 // if args[1] is not a property on args[0] | 2034 // if args[1] is not a property on args[0] |
2075 // returns undefined | 2035 // returns undefined |
2076 // if args[1] is a data property on args[0] | 2036 // if args[1] is a data property on args[0] |
2077 // [false, value, Writeable, Enumerable, Configurable] | 2037 // [false, value, Writeable, Enumerable, Configurable] |
2078 // if args[1] is an accessor on args[0] | 2038 // if args[1] is an accessor on args[0] |
2079 // [true, GetFunction, SetFunction, Enumerable, Configurable] | 2039 // [true, GetFunction, SetFunction, Enumerable, Configurable] |
(...skipping 13131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15211 } | 15171 } |
15212 return NULL; | 15172 return NULL; |
15213 } | 15173 } |
15214 | 15174 |
15215 | 15175 |
15216 const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) { | 15176 const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) { |
15217 return &(kIntrinsicFunctions[static_cast<int>(id)]); | 15177 return &(kIntrinsicFunctions[static_cast<int>(id)]); |
15218 } | 15178 } |
15219 | 15179 |
15220 } } // namespace v8::internal | 15180 } } // namespace v8::internal |
OLD | NEW |