| 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 | 6 |
| 7 #include <fstream> // NOLINT(readability/streams) | 7 #include <fstream> // NOLINT(readability/streams) |
| 8 #include <sstream> | 8 #include <sstream> |
| 9 | 9 |
| 10 #include "src/v8.h" | 10 #include "src/v8.h" |
| (...skipping 717 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 728 if (!constructor->shared()->IsApiFunction()) return NULL; | 728 if (!constructor->shared()->IsApiFunction()) return NULL; |
| 729 | 729 |
| 730 Object* data_obj = | 730 Object* data_obj = |
| 731 constructor->shared()->get_api_func_data()->access_check_info(); | 731 constructor->shared()->get_api_func_data()->access_check_info(); |
| 732 if (data_obj == isolate->heap()->undefined_value()) return NULL; | 732 if (data_obj == isolate->heap()->undefined_value()) return NULL; |
| 733 | 733 |
| 734 return AccessCheckInfo::cast(data_obj); | 734 return AccessCheckInfo::cast(data_obj); |
| 735 } | 735 } |
| 736 | 736 |
| 737 | 737 |
| 738 void Isolate::ReportFailedAccessCheck(Handle<JSObject> receiver, | 738 void Isolate::ReportFailedAccessCheck(Handle<JSObject> receiver) { |
| 739 v8::AccessType type) { | |
| 740 if (!thread_local_top()->failed_access_check_callback_) { | 739 if (!thread_local_top()->failed_access_check_callback_) { |
| 741 Handle<String> message = factory()->InternalizeUtf8String("no access"); | 740 Handle<String> message = factory()->InternalizeUtf8String("no access"); |
| 742 ScheduleThrow(*factory()->NewTypeError(message)); | 741 ScheduleThrow(*factory()->NewTypeError(message)); |
| 743 return; | 742 return; |
| 744 } | 743 } |
| 745 | 744 |
| 746 DCHECK(receiver->IsAccessCheckNeeded()); | 745 DCHECK(receiver->IsAccessCheckNeeded()); |
| 747 DCHECK(context()); | 746 DCHECK(context()); |
| 748 | 747 |
| 749 // Get the data object from access check info. | 748 // Get the data object from access check info. |
| 750 HandleScope scope(this); | 749 HandleScope scope(this); |
| 751 Handle<Object> data; | 750 Handle<Object> data; |
| 752 { DisallowHeapAllocation no_gc; | 751 { DisallowHeapAllocation no_gc; |
| 753 AccessCheckInfo* access_check_info = GetAccessCheckInfo(this, receiver); | 752 AccessCheckInfo* access_check_info = GetAccessCheckInfo(this, receiver); |
| 754 if (!access_check_info) return; | 753 if (!access_check_info) return; |
| 755 data = handle(access_check_info->data(), this); | 754 data = handle(access_check_info->data(), this); |
| 756 } | 755 } |
| 757 | 756 |
| 758 // Leaving JavaScript. | 757 // Leaving JavaScript. |
| 759 VMState<EXTERNAL> state(this); | 758 VMState<EXTERNAL> state(this); |
| 760 thread_local_top()->failed_access_check_callback_( | 759 thread_local_top()->failed_access_check_callback_( |
| 761 v8::Utils::ToLocal(receiver), | 760 v8::Utils::ToLocal(receiver), v8::ACCESS_HAS, v8::Utils::ToLocal(data)); |
| 762 type, | |
| 763 v8::Utils::ToLocal(data)); | |
| 764 } | 761 } |
| 765 | 762 |
| 766 | 763 |
| 767 enum MayAccessDecision { | |
| 768 YES, NO, UNKNOWN | |
| 769 }; | |
| 770 | |
| 771 | |
| 772 static MayAccessDecision MayAccessPreCheck(Isolate* isolate, | |
| 773 Handle<JSObject> receiver, | |
| 774 v8::AccessType type) { | |
| 775 DisallowHeapAllocation no_gc; | |
| 776 // During bootstrapping, callback functions are not enabled yet. | |
| 777 if (isolate->bootstrapper()->IsActive()) return YES; | |
| 778 | |
| 779 if (receiver->IsJSGlobalProxy()) { | |
| 780 Object* receiver_context = JSGlobalProxy::cast(*receiver)->native_context(); | |
| 781 if (!receiver_context->IsContext()) return NO; | |
| 782 | |
| 783 // Get the native context of current top context. | |
| 784 // avoid using Isolate::native_context() because it uses Handle. | |
| 785 Context* native_context = | |
| 786 isolate->context()->global_object()->native_context(); | |
| 787 if (receiver_context == native_context) return YES; | |
| 788 | |
| 789 if (Context::cast(receiver_context)->security_token() == | |
| 790 native_context->security_token()) | |
| 791 return YES; | |
| 792 } | |
| 793 | |
| 794 return UNKNOWN; | |
| 795 } | |
| 796 | |
| 797 | |
| 798 bool Isolate::IsInternallyUsedPropertyName(Handle<Object> name) { | 764 bool Isolate::IsInternallyUsedPropertyName(Handle<Object> name) { |
| 799 return name.is_identical_to(factory()->hidden_string()) || | 765 return name.is_identical_to(factory()->hidden_string()) || |
| 800 name.is_identical_to(factory()->prototype_users_symbol()); | 766 name.is_identical_to(factory()->prototype_users_symbol()); |
| 801 } | 767 } |
| 802 | 768 |
| 803 | 769 |
| 804 bool Isolate::IsInternallyUsedPropertyName(Object* name) { | 770 bool Isolate::IsInternallyUsedPropertyName(Object* name) { |
| 805 return name == heap()->hidden_string() || | 771 return name == heap()->hidden_string() || |
| 806 name == heap()->prototype_users_symbol(); | 772 name == heap()->prototype_users_symbol(); |
| 807 } | 773 } |
| 808 | 774 |
| 809 | 775 |
| 810 bool Isolate::MayNamedAccess(Handle<JSObject> receiver, | 776 bool Isolate::MayAccess(Handle<JSObject> receiver) { |
| 811 Handle<Object> key, | |
| 812 v8::AccessType type) { | |
| 813 DCHECK(receiver->IsJSGlobalProxy() || receiver->IsAccessCheckNeeded()); | 777 DCHECK(receiver->IsJSGlobalProxy() || receiver->IsAccessCheckNeeded()); |
| 814 | 778 |
| 815 // Skip checks for internally used properties. Note, we do not | |
| 816 // require existence of a context in this case. | |
| 817 if (IsInternallyUsedPropertyName(key)) return true; | |
| 818 | |
| 819 // Check for compatibility between the security tokens in the | 779 // Check for compatibility between the security tokens in the |
| 820 // current lexical context and the accessed object. | 780 // current lexical context and the accessed object. |
| 821 DCHECK(context()); | 781 DCHECK(context()); |
| 822 | 782 |
| 823 MayAccessDecision decision = MayAccessPreCheck(this, receiver, type); | 783 { |
| 824 if (decision != UNKNOWN) return decision == YES; | 784 DisallowHeapAllocation no_gc; |
| 785 // During bootstrapping, callback functions are not enabled yet. |
| 786 if (bootstrapper()->IsActive()) return true; |
| 787 |
| 788 if (receiver->IsJSGlobalProxy()) { |
| 789 Object* receiver_context = |
| 790 JSGlobalProxy::cast(*receiver)->native_context(); |
| 791 if (!receiver_context->IsContext()) return false; |
| 792 |
| 793 // Get the native context of current top context. |
| 794 // avoid using Isolate::native_context() because it uses Handle. |
| 795 Context* native_context = context()->global_object()->native_context(); |
| 796 if (receiver_context == native_context) return true; |
| 797 |
| 798 if (Context::cast(receiver_context)->security_token() == |
| 799 native_context->security_token()) |
| 800 return true; |
| 801 } |
| 802 } |
| 825 | 803 |
| 826 HandleScope scope(this); | 804 HandleScope scope(this); |
| 827 Handle<Object> data; | 805 Handle<Object> data; |
| 828 v8::NamedSecurityCallback callback; | 806 v8::NamedSecurityCallback callback; |
| 829 { DisallowHeapAllocation no_gc; | 807 { DisallowHeapAllocation no_gc; |
| 830 AccessCheckInfo* access_check_info = GetAccessCheckInfo(this, receiver); | 808 AccessCheckInfo* access_check_info = GetAccessCheckInfo(this, receiver); |
| 831 if (!access_check_info) return false; | 809 if (!access_check_info) return false; |
| 832 Object* fun_obj = access_check_info->named_callback(); | 810 Object* fun_obj = access_check_info->named_callback(); |
| 833 callback = v8::ToCData<v8::NamedSecurityCallback>(fun_obj); | 811 callback = v8::ToCData<v8::NamedSecurityCallback>(fun_obj); |
| 834 if (!callback) return false; | 812 if (!callback) return false; |
| 835 data = handle(access_check_info->data(), this); | 813 data = handle(access_check_info->data(), this); |
| 836 } | 814 } |
| 837 | 815 |
| 838 LOG(this, ApiNamedSecurityCheck(*key)); | 816 LOG(this, ApiSecurityCheck()); |
| 839 | 817 |
| 840 // Leaving JavaScript. | 818 // Leaving JavaScript. |
| 841 VMState<EXTERNAL> state(this); | 819 VMState<EXTERNAL> state(this); |
| 842 return callback(v8::Utils::ToLocal(receiver), | 820 Handle<Object> key = factory()->undefined_value(); |
| 843 v8::Utils::ToLocal(key), | 821 return callback(v8::Utils::ToLocal(receiver), v8::Utils::ToLocal(key), |
| 844 type, | 822 v8::ACCESS_HAS, v8::Utils::ToLocal(data)); |
| 845 v8::Utils::ToLocal(data)); | |
| 846 } | 823 } |
| 847 | 824 |
| 848 | 825 |
| 849 bool Isolate::MayIndexedAccess(Handle<JSObject> receiver, | |
| 850 uint32_t index, | |
| 851 v8::AccessType type) { | |
| 852 DCHECK(receiver->IsJSGlobalProxy() || receiver->IsAccessCheckNeeded()); | |
| 853 // Check for compatibility between the security tokens in the | |
| 854 // current lexical context and the accessed object. | |
| 855 DCHECK(context()); | |
| 856 | |
| 857 MayAccessDecision decision = MayAccessPreCheck(this, receiver, type); | |
| 858 if (decision != UNKNOWN) return decision == YES; | |
| 859 | |
| 860 HandleScope scope(this); | |
| 861 Handle<Object> data; | |
| 862 v8::IndexedSecurityCallback callback; | |
| 863 { DisallowHeapAllocation no_gc; | |
| 864 // Get named access check callback | |
| 865 AccessCheckInfo* access_check_info = GetAccessCheckInfo(this, receiver); | |
| 866 if (!access_check_info) return false; | |
| 867 Object* fun_obj = access_check_info->indexed_callback(); | |
| 868 callback = v8::ToCData<v8::IndexedSecurityCallback>(fun_obj); | |
| 869 if (!callback) return false; | |
| 870 data = handle(access_check_info->data(), this); | |
| 871 } | |
| 872 | |
| 873 LOG(this, ApiIndexedSecurityCheck(index)); | |
| 874 | |
| 875 // Leaving JavaScript. | |
| 876 VMState<EXTERNAL> state(this); | |
| 877 return callback( | |
| 878 v8::Utils::ToLocal(receiver), index, type, v8::Utils::ToLocal(data)); | |
| 879 } | |
| 880 | |
| 881 | |
| 882 const char* const Isolate::kStackOverflowMessage = | 826 const char* const Isolate::kStackOverflowMessage = |
| 883 "Uncaught RangeError: Maximum call stack size exceeded"; | 827 "Uncaught RangeError: Maximum call stack size exceeded"; |
| 884 | 828 |
| 885 | 829 |
| 886 Object* Isolate::StackOverflow() { | 830 Object* Isolate::StackOverflow() { |
| 887 HandleScope scope(this); | 831 HandleScope scope(this); |
| 888 // At this point we cannot create an Error object using its javascript | 832 // At this point we cannot create an Error object using its javascript |
| 889 // constructor. Instead, we copy the pre-constructed boilerplate and | 833 // constructor. Instead, we copy the pre-constructed boilerplate and |
| 890 // attach the stack trace as a hidden property. | 834 // attach the stack trace as a hidden property. |
| 891 Handle<String> key = factory()->stack_overflow_string(); | 835 Handle<String> key = factory()->stack_overflow_string(); |
| (...skipping 1715 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2607 if (prev_ && prev_->Intercept(flag)) return true; | 2551 if (prev_ && prev_->Intercept(flag)) return true; |
| 2608 // Then check whether this scope intercepts. | 2552 // Then check whether this scope intercepts. |
| 2609 if ((flag & intercept_mask_)) { | 2553 if ((flag & intercept_mask_)) { |
| 2610 intercepted_flags_ |= flag; | 2554 intercepted_flags_ |= flag; |
| 2611 return true; | 2555 return true; |
| 2612 } | 2556 } |
| 2613 return false; | 2557 return false; |
| 2614 } | 2558 } |
| 2615 | 2559 |
| 2616 } } // namespace v8::internal | 2560 } } // namespace v8::internal |
| OLD | NEW |