Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(585)

Side by Side Diff: src/isolate.cc

Issue 234913003: Allow allocation and GC in access check callbacks. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: added TODOs, addressed comments Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/isolate.h ('k') | src/objects.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 675 matching lines...) Expand 10 before | Expand all | Expand 10 after
686 accumulator->Add("=====================\n\n"); 686 accumulator->Add("=====================\n\n");
687 } 687 }
688 688
689 689
690 void Isolate::SetFailedAccessCheckCallback( 690 void Isolate::SetFailedAccessCheckCallback(
691 v8::FailedAccessCheckCallback callback) { 691 v8::FailedAccessCheckCallback callback) {
692 thread_local_top()->failed_access_check_callback_ = callback; 692 thread_local_top()->failed_access_check_callback_ = callback;
693 } 693 }
694 694
695 695
696 void Isolate::ReportFailedAccessCheck(JSObject* receiver, v8::AccessType type) { 696 static inline AccessCheckInfo* GetAccessCheckInfo(Isolate* isolate,
697 Handle<JSObject> receiver) {
698 JSFunction* constructor = JSFunction::cast(receiver->map()->constructor());
699 if (!constructor->shared()->IsApiFunction()) return NULL;
700
701 Object* data_obj =
702 constructor->shared()->get_api_func_data()->access_check_info();
703 if (data_obj == isolate->heap()->undefined_value()) return NULL;
704
705 return AccessCheckInfo::cast(data_obj);
706 }
707
708
709 void Isolate::ReportFailedAccessCheck(Handle<JSObject> receiver,
710 v8::AccessType type) {
697 if (!thread_local_top()->failed_access_check_callback_) return; 711 if (!thread_local_top()->failed_access_check_callback_) return;
698 712
699 ASSERT(receiver->IsAccessCheckNeeded()); 713 ASSERT(receiver->IsAccessCheckNeeded());
700 ASSERT(context()); 714 ASSERT(context());
701 715
702 // Get the data object from access check info. 716 // Get the data object from access check info.
703 JSFunction* constructor = JSFunction::cast(receiver->map()->constructor()); 717 HandleScope scope(this);
704 if (!constructor->shared()->IsApiFunction()) return; 718 Handle<Object> data;
705 Object* data_obj = 719 { DisallowHeapAllocation no_gc;
706 constructor->shared()->get_api_func_data()->access_check_info(); 720 AccessCheckInfo* access_check_info = GetAccessCheckInfo(this, receiver);
707 if (data_obj == heap_.undefined_value()) return; 721 if (!access_check_info) return;
722 data = handle(access_check_info->data(), this);
723 }
708 724
709 HandleScope scope(this); 725 // Leaving JavaScript.
710 Handle<JSObject> receiver_handle(receiver); 726 VMState<EXTERNAL> state(this);
711 Handle<Object> data(AccessCheckInfo::cast(data_obj)->data(), this); 727 thread_local_top()->failed_access_check_callback_(
712 { VMState<EXTERNAL> state(this); 728 v8::Utils::ToLocal(receiver),
713 thread_local_top()->failed_access_check_callback_(
714 v8::Utils::ToLocal(receiver_handle),
715 type, 729 type,
716 v8::Utils::ToLocal(data)); 730 v8::Utils::ToLocal(data));
717 }
718 } 731 }
719 732
720 733
721 enum MayAccessDecision { 734 enum MayAccessDecision {
722 YES, NO, UNKNOWN 735 YES, NO, UNKNOWN
723 }; 736 };
724 737
725 738
726 static MayAccessDecision MayAccessPreCheck(Isolate* isolate, 739 static MayAccessDecision MayAccessPreCheck(Isolate* isolate,
727 JSObject* receiver, 740 Handle<JSObject> receiver,
728 v8::AccessType type) { 741 v8::AccessType type) {
742 DisallowHeapAllocation no_gc;
729 // During bootstrapping, callback functions are not enabled yet. 743 // During bootstrapping, callback functions are not enabled yet.
730 if (isolate->bootstrapper()->IsActive()) return YES; 744 if (isolate->bootstrapper()->IsActive()) return YES;
731 745
732 if (receiver->IsJSGlobalProxy()) { 746 if (receiver->IsJSGlobalProxy()) {
733 Object* receiver_context = JSGlobalProxy::cast(receiver)->native_context(); 747 Object* receiver_context = JSGlobalProxy::cast(*receiver)->native_context();
734 if (!receiver_context->IsContext()) return NO; 748 if (!receiver_context->IsContext()) return NO;
735 749
736 // Get the native context of current top context. 750 // Get the native context of current top context.
737 // avoid using Isolate::native_context() because it uses Handle. 751 // avoid using Isolate::native_context() because it uses Handle.
738 Context* native_context = 752 Context* native_context =
739 isolate->context()->global_object()->native_context(); 753 isolate->context()->global_object()->native_context();
740 if (receiver_context == native_context) return YES; 754 if (receiver_context == native_context) return YES;
741 755
742 if (Context::cast(receiver_context)->security_token() == 756 if (Context::cast(receiver_context)->security_token() ==
743 native_context->security_token()) 757 native_context->security_token())
744 return YES; 758 return YES;
745 } 759 }
746 760
747 return UNKNOWN; 761 return UNKNOWN;
748 } 762 }
749 763
750 764
751 bool Isolate::MayNamedAccess(JSObject* receiver, Object* key, 765 bool Isolate::MayNamedAccess(Handle<JSObject> receiver,
766 Handle<Object> key,
752 v8::AccessType type) { 767 v8::AccessType type) {
753 ASSERT(receiver->IsJSGlobalProxy() || receiver->IsAccessCheckNeeded()); 768 ASSERT(receiver->IsJSGlobalProxy() || receiver->IsAccessCheckNeeded());
754 769
755 // The callers of this method are not expecting a GC.
756 DisallowHeapAllocation no_gc;
757
758 // Skip checks for hidden properties access. Note, we do not 770 // Skip checks for hidden properties access. Note, we do not
759 // require existence of a context in this case. 771 // require existence of a context in this case.
760 if (key == heap_.hidden_string()) return true; 772 if (key.is_identical_to(factory()->hidden_string())) return true;
761 773
762 // Check for compatibility between the security tokens in the 774 // Check for compatibility between the security tokens in the
763 // current lexical context and the accessed object. 775 // current lexical context and the accessed object.
764 ASSERT(context()); 776 ASSERT(context());
765 777
766 MayAccessDecision decision = MayAccessPreCheck(this, receiver, type); 778 MayAccessDecision decision = MayAccessPreCheck(this, receiver, type);
767 if (decision != UNKNOWN) return decision == YES; 779 if (decision != UNKNOWN) return decision == YES;
768 780
769 // Get named access check callback 781 HandleScope scope(this);
770 JSFunction* constructor = JSFunction::cast(receiver->map()->constructor()); 782 Handle<Object> data;
771 if (!constructor->shared()->IsApiFunction()) return false; 783 v8::NamedSecurityCallback callback;
784 { DisallowHeapAllocation no_gc;
785 AccessCheckInfo* access_check_info = GetAccessCheckInfo(this, receiver);
786 if (!access_check_info) return false;
787 Object* fun_obj = access_check_info->named_callback();
788 callback = v8::ToCData<v8::NamedSecurityCallback>(fun_obj);
789 if (!callback) return false;
790 data = handle(access_check_info->data(), this);
791 }
772 792
773 Object* data_obj = 793 LOG(this, ApiNamedSecurityCheck(*key));
774 constructor->shared()->get_api_func_data()->access_check_info();
775 if (data_obj == heap_.undefined_value()) return false;
776 794
777 Object* fun_obj = AccessCheckInfo::cast(data_obj)->named_callback(); 795 // Leaving JavaScript.
778 v8::NamedSecurityCallback callback = 796 VMState<EXTERNAL> state(this);
779 v8::ToCData<v8::NamedSecurityCallback>(fun_obj); 797 return callback(v8::Utils::ToLocal(receiver),
780 798 v8::Utils::ToLocal(key),
781 if (!callback) return false; 799 type,
782 800 v8::Utils::ToLocal(data));
783 HandleScope scope(this);
784 Handle<JSObject> receiver_handle(receiver, this);
785 Handle<Object> key_handle(key, this);
786 Handle<Object> data(AccessCheckInfo::cast(data_obj)->data(), this);
787 LOG(this, ApiNamedSecurityCheck(key));
788 bool result = false;
789 {
790 // Leaving JavaScript.
791 VMState<EXTERNAL> state(this);
792 result = callback(v8::Utils::ToLocal(receiver_handle),
793 v8::Utils::ToLocal(key_handle),
794 type,
795 v8::Utils::ToLocal(data));
796 }
797 return result;
798 } 801 }
799 802
800 803
801 bool Isolate::MayIndexedAccess(JSObject* receiver, 804 bool Isolate::MayIndexedAccess(Handle<JSObject> receiver,
802 uint32_t index, 805 uint32_t index,
803 v8::AccessType type) { 806 v8::AccessType type) {
804 ASSERT(receiver->IsJSGlobalProxy() || receiver->IsAccessCheckNeeded()); 807 ASSERT(receiver->IsJSGlobalProxy() || receiver->IsAccessCheckNeeded());
805 // Check for compatibility between the security tokens in the 808 // Check for compatibility between the security tokens in the
806 // current lexical context and the accessed object. 809 // current lexical context and the accessed object.
807 ASSERT(context()); 810 ASSERT(context());
808 811
809 MayAccessDecision decision = MayAccessPreCheck(this, receiver, type); 812 MayAccessDecision decision = MayAccessPreCheck(this, receiver, type);
810 if (decision != UNKNOWN) return decision == YES; 813 if (decision != UNKNOWN) return decision == YES;
811 814
812 // Get indexed access check callback 815 HandleScope scope(this);
813 JSFunction* constructor = JSFunction::cast(receiver->map()->constructor()); 816 Handle<Object> data;
814 if (!constructor->shared()->IsApiFunction()) return false; 817 v8::IndexedSecurityCallback callback;
818 { DisallowHeapAllocation no_gc;
819 // Get named access check callback
820 AccessCheckInfo* access_check_info = GetAccessCheckInfo(this, receiver);
821 if (!access_check_info) return false;
822 Object* fun_obj = access_check_info->indexed_callback();
823 callback = v8::ToCData<v8::IndexedSecurityCallback>(fun_obj);
824 if (!callback) return false;
825 data = handle(access_check_info->data(), this);
826 }
815 827
816 Object* data_obj = 828 LOG(this, ApiIndexedSecurityCheck(index));
817 constructor->shared()->get_api_func_data()->access_check_info();
818 if (data_obj == heap_.undefined_value()) return false;
819 829
820 Object* fun_obj = AccessCheckInfo::cast(data_obj)->indexed_callback(); 830 // Leaving JavaScript.
821 v8::IndexedSecurityCallback callback = 831 VMState<EXTERNAL> state(this);
822 v8::ToCData<v8::IndexedSecurityCallback>(fun_obj); 832 return callback(
823 833 v8::Utils::ToLocal(receiver), index, type, v8::Utils::ToLocal(data));
824 if (!callback) return false;
825
826 HandleScope scope(this);
827 Handle<JSObject> receiver_handle(receiver, this);
828 Handle<Object> data(AccessCheckInfo::cast(data_obj)->data(), this);
829 LOG(this, ApiIndexedSecurityCheck(index));
830 bool result = false;
831 {
832 // Leaving JavaScript.
833 VMState<EXTERNAL> state(this);
834 result = callback(v8::Utils::ToLocal(receiver_handle),
835 index,
836 type,
837 v8::Utils::ToLocal(data));
838 }
839 return result;
840 } 834 }
841 835
842 836
843 const char* const Isolate::kStackOverflowMessage = 837 const char* const Isolate::kStackOverflowMessage =
844 "Uncaught RangeError: Maximum call stack size exceeded"; 838 "Uncaught RangeError: Maximum call stack size exceeded";
845 839
846 840
847 Failure* Isolate::StackOverflow() { 841 Failure* Isolate::StackOverflow() {
848 HandleScope scope(this); 842 HandleScope scope(this);
849 // At this point we cannot create an Error object using its javascript 843 // At this point we cannot create an Error object using its javascript
(...skipping 1437 matching lines...) Expand 10 before | Expand all | Expand 10 after
2287 Handle<JSObject> obj = factory()->NewJSObjectFromMap(map); 2281 Handle<JSObject> obj = factory()->NewJSObjectFromMap(map);
2288 JSObject::NormalizeProperties(obj, KEEP_INOBJECT_PROPERTIES, 8); 2282 JSObject::NormalizeProperties(obj, KEEP_INOBJECT_PROPERTIES, 8);
2289 JSObject::SetProperty(registry, name, obj, NONE, STRICT).Assert(); 2283 JSObject::SetProperty(registry, name, obj, NONE, STRICT).Assert();
2290 } 2284 }
2291 } 2285 }
2292 return Handle<JSObject>::cast(factory()->symbol_registry()); 2286 return Handle<JSObject>::cast(factory()->symbol_registry());
2293 } 2287 }
2294 2288
2295 2289
2296 } } // namespace v8::internal 2290 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/isolate.h ('k') | src/objects.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698