| 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 |