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

Side by Side Diff: src/builtins/builtins-promise.cc

Issue 2628863002: Do security checks in the promise constructor (Closed)
Patch Set: Created 3 years, 11 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
OLDNEW
1 // Copyright 2016 the V8 project authors. All rights reserved. 1 // Copyright 2016 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 "src/builtins/builtins-promise.h" 5 #include "src/builtins/builtins-promise.h"
6 #include "src/builtins/builtins-constructor.h" 6 #include "src/builtins/builtins-constructor.h"
7 #include "src/builtins/builtins-utils.h" 7 #include "src/builtins/builtins-utils.h"
8 #include "src/builtins/builtins.h" 8 #include "src/builtins/builtins.h"
9 #include "src/code-factory.h" 9 #include "src/code-factory.h"
10 #include "src/code-stub-assembler.h" 10 #include "src/code-stub-assembler.h"
(...skipping 886 matching lines...) Expand 10 before | Expand all | Expand 10 after
897 Heap::kUndefinedValueRootIndex); 897 Heap::kUndefinedValueRootIndex);
898 StoreObjectFieldRoot(promise, JSPromise::kDeferredOnRejectOffset, 898 StoreObjectFieldRoot(promise, JSPromise::kDeferredOnRejectOffset,
899 Heap::kUndefinedValueRootIndex); 899 Heap::kUndefinedValueRootIndex);
900 StoreObjectFieldRoot(promise, JSPromise::kFulfillReactionsOffset, 900 StoreObjectFieldRoot(promise, JSPromise::kFulfillReactionsOffset,
901 Heap::kUndefinedValueRootIndex); 901 Heap::kUndefinedValueRootIndex);
902 StoreObjectFieldRoot(promise, JSPromise::kRejectReactionsOffset, 902 StoreObjectFieldRoot(promise, JSPromise::kRejectReactionsOffset,
903 Heap::kUndefinedValueRootIndex); 903 Heap::kUndefinedValueRootIndex);
904 } 904 }
905 } 905 }
906 906
907 void PromiseBuiltinsAssembler::BranchIfAccessCheckFailed(
908 Node* context, Node* promise_constructor, Node* executor,
909 Label* if_noaccess) {
910 Variable var_executor(this, MachineRepresentation::kTagged);
911 var_executor.Bind(executor);
912 Label has_access(this), call_runtime(this, Label::kDeferred);
913
914 // If executor is a bound function, load the bound function until we've
915 // reached an actual function.
916 Label found_function(this), loop_over_bound_function(this, &var_executor);
917 Goto(&loop_over_bound_function);
918 Bind(&loop_over_bound_function);
gsathya 2017/01/11 17:27:31 i wonder if its better to duplicate the IsJSFuncti
jochen (gone - plz use gerrit) 2017/01/11 18:09:57 afaik that shouldn't make that much of a differenc
Igor Sheludko 2017/01/12 08:31:11 I think it's fine to avoid marking the block as de
919 {
920 GotoIf(IsJSFunction(var_executor.value()), &found_function);
921 GotoUnless(IsJSBoundFunction(var_executor.value()), &call_runtime);
Igor Sheludko 2017/01/12 08:31:11 Here you are loading map and then instance type se
922 var_executor.Bind(LoadObjectField(
923 var_executor.value(), JSBoundFunction::kBoundTargetFunctionOffset));
924 Goto(&loop_over_bound_function);
925 }
926
927 // Load the context from the function and compare it to the Promise
928 // constructor's context. If they match, everything is fine, otherwise, bail
929 // out to the runtime.
930 Bind(&found_function);
931 {
932 Node* native_context = LoadNativeContext(context);
gsathya 2017/01/11 17:27:31 this can be an argument to this function, no need
jochen (gone - plz use gerrit) 2017/01/11 18:09:57 done
933 Node* function_context =
934 LoadObjectField(var_executor.value(), JSFunction::kContextOffset);
935 Node* native_function_context = LoadNativeContext(function_context);
936 Branch(WordEqual(native_context, native_function_context), &has_access,
937 &call_runtime);
938 }
939
940 Bind(&call_runtime);
941 {
942 Branch(WordEqual(CallRuntime(Runtime::kAllowDynamicFunction, context,
943 promise_constructor),
944 BooleanConstant(true)),
945 &has_access, if_noaccess);
946 }
947
948 Bind(&has_access);
949 }
950
907 // ES#sec-promise-reject-functions 951 // ES#sec-promise-reject-functions
908 // Promise Reject Functions 952 // Promise Reject Functions
909 TF_BUILTIN(PromiseRejectClosure, PromiseBuiltinsAssembler) { 953 TF_BUILTIN(PromiseRejectClosure, PromiseBuiltinsAssembler) {
910 Node* const value = Parameter(1); 954 Node* const value = Parameter(1);
911 Node* const context = Parameter(4); 955 Node* const context = Parameter(4);
912 956
913 Label out(this); 957 Label out(this);
914 958
915 // 3. Let alreadyResolved be F.[[AlreadyResolved]]. 959 // 3. Let alreadyResolved be F.[[AlreadyResolved]].
916 int has_already_visited_slot = PromiseUtils::kAlreadyVisitedSlot; 960 int has_already_visited_slot = PromiseUtils::kAlreadyVisitedSlot;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
954 998
955 Node* const executor_map = LoadMap(executor); 999 Node* const executor_map = LoadMap(executor);
956 GotoUnless(IsCallableMap(executor_map), &if_notcallable); 1000 GotoUnless(IsCallableMap(executor_map), &if_notcallable);
957 1001
958 Node* const native_context = LoadNativeContext(context); 1002 Node* const native_context = LoadNativeContext(context);
959 Node* const promise_fun = 1003 Node* const promise_fun =
960 LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX); 1004 LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
961 Node* const is_debug_active = IsDebugActive(); 1005 Node* const is_debug_active = IsDebugActive();
962 Label if_targetisnotmodified(this), 1006 Label if_targetisnotmodified(this),
963 if_targetismodified(this, Label::kDeferred), run_executor(this), 1007 if_targetismodified(this, Label::kDeferred), run_executor(this),
964 debug_push(this); 1008 debug_push(this), if_noaccess(this, Label::kDeferred);
1009
1010 BranchIfAccessCheckFailed(context, promise_fun, executor, &if_noaccess);
965 1011
966 Branch(WordEqual(promise_fun, new_target), &if_targetisnotmodified, 1012 Branch(WordEqual(promise_fun, new_target), &if_targetisnotmodified,
967 &if_targetismodified); 1013 &if_targetismodified);
968 1014
969 Variable var_result(this, MachineRepresentation::kTagged), 1015 Variable var_result(this, MachineRepresentation::kTagged),
970 var_reject_call(this, MachineRepresentation::kTagged), 1016 var_reject_call(this, MachineRepresentation::kTagged),
971 var_reason(this, MachineRepresentation::kTagged); 1017 var_reason(this, MachineRepresentation::kTagged);
972 1018
973 Bind(&if_targetisnotmodified); 1019 Bind(&if_targetisnotmodified);
974 { 1020 {
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
1039 } 1085 }
1040 1086
1041 // 2. If IsCallable(executor) is false, throw a TypeError exception. 1087 // 2. If IsCallable(executor) is false, throw a TypeError exception.
1042 Bind(&if_notcallable); 1088 Bind(&if_notcallable);
1043 { 1089 {
1044 Node* const message_id = 1090 Node* const message_id =
1045 SmiConstant(MessageTemplate::kResolverNotAFunction); 1091 SmiConstant(MessageTemplate::kResolverNotAFunction);
1046 CallRuntime(Runtime::kThrowTypeError, context, message_id, executor); 1092 CallRuntime(Runtime::kThrowTypeError, context, message_id, executor);
1047 Return(UndefinedConstant()); // Never reached. 1093 Return(UndefinedConstant()); // Never reached.
1048 } 1094 }
1095
1096 // Silently fail if the stack looks fishy.
1097 Bind(&if_noaccess);
1098 {
1099 Node* const counter_id =
1100 SmiConstant(v8::Isolate::kPromiseConstructorReturnedUndefined);
1101 CallRuntime(Runtime::kCountUsage, context, counter_id);
1102 Return(UndefinedConstant());
1103 }
1049 } 1104 }
1050 1105
1051 TF_BUILTIN(PromiseInternalConstructor, PromiseBuiltinsAssembler) { 1106 TF_BUILTIN(PromiseInternalConstructor, PromiseBuiltinsAssembler) {
1052 Node* const parent = Parameter(1); 1107 Node* const parent = Parameter(1);
1053 Node* const context = Parameter(4); 1108 Node* const context = Parameter(4);
1054 Return(AllocateAndInitJSPromise(context, parent)); 1109 Return(AllocateAndInitJSPromise(context, parent));
1055 } 1110 }
1056 1111
1057 TF_BUILTIN(IsPromise, PromiseBuiltinsAssembler) { 1112 TF_BUILTIN(IsPromise, PromiseBuiltinsAssembler) {
1058 Node* const maybe_promise = Parameter(1); 1113 Node* const maybe_promise = Parameter(1);
(...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after
1449 1504
1450 // 5. Return promiseCapability.[[Promise]]. 1505 // 5. Return promiseCapability.[[Promise]].
1451 Node* const promise = 1506 Node* const promise =
1452 LoadObjectField(capability, JSPromiseCapability::kPromiseOffset); 1507 LoadObjectField(capability, JSPromiseCapability::kPromiseOffset);
1453 Return(promise); 1508 Return(promise);
1454 } 1509 }
1455 } 1510 }
1456 1511
1457 } // namespace internal 1512 } // namespace internal
1458 } // namespace v8 1513 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698