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

Side by Side Diff: src/runtime/runtime-scopes.cc

Issue 1683103002: [compiler] Sanitize entry points to LookupSlot access. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: REBASE. Fixes. Comments. Created 4 years, 10 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
« no previous file with comments | « src/runtime/runtime.h ('k') | test/cctest/interpreter/test-bytecode-generator.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 2014 the V8 project authors. All rights reserved. 1 // Copyright 2014 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/runtime/runtime-utils.h" 5 #include "src/runtime/runtime-utils.h"
6 6
7 #include "src/accessors.h" 7 #include "src/accessors.h"
8 #include "src/arguments.h" 8 #include "src/arguments.h"
9 #include "src/ast/scopeinfo.h" 9 #include "src/ast/scopeinfo.h"
10 #include "src/ast/scopes.h" 10 #include "src/ast/scopes.h"
(...skipping 914 matching lines...) Expand 10 before | Expand all | Expand 10 after
925 } 925 }
926 } 926 }
927 927
928 DCHECK(!isolate->has_pending_exception()); 928 DCHECK(!isolate->has_pending_exception());
929 return isolate->heap()->undefined_value(); 929 return isolate->heap()->undefined_value();
930 } 930 }
931 931
932 932
933 RUNTIME_FUNCTION(Runtime_DeleteLookupSlot) { 933 RUNTIME_FUNCTION(Runtime_DeleteLookupSlot) {
934 HandleScope scope(isolate); 934 HandleScope scope(isolate);
935 DCHECK(args.length() == 2); 935 DCHECK_EQ(1, args.length());
936 936 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
937 CONVERT_ARG_HANDLE_CHECKED(Context, context, 0);
938 CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
939 937
940 int index; 938 int index;
941 PropertyAttributes attributes; 939 PropertyAttributes attributes;
942 ContextLookupFlags flags = FOLLOW_CHAINS; 940 BindingFlags flags;
943 BindingFlags binding_flags; 941 Handle<Object> holder = isolate->context()->Lookup(
944 Handle<Object> holder = 942 name, FOLLOW_CHAINS, &index, &attributes, &flags);
945 context->Lookup(name, flags, &index, &attributes, &binding_flags);
946 943
947 // If the slot was not found the result is true. 944 // If the slot was not found the result is true.
948 if (holder.is_null()) { 945 if (holder.is_null()) {
949 // In case of JSProxy, an exception might have been thrown. 946 // In case of JSProxy, an exception might have been thrown.
950 if (isolate->has_pending_exception()) return isolate->heap()->exception(); 947 if (isolate->has_pending_exception()) return isolate->heap()->exception();
951 return isolate->heap()->true_value(); 948 return isolate->heap()->true_value();
952 } 949 }
953 950
954 // If the slot was found in a context, it should be DONT_DELETE. 951 // If the slot was found in a context, it should be DONT_DELETE.
955 if (holder->IsContext()) { 952 if (holder->IsContext()) {
956 return isolate->heap()->false_value(); 953 return isolate->heap()->false_value();
957 } 954 }
958 955
959 // The slot was found in a JSReceiver, either a context extension object, 956 // The slot was found in a JSReceiver, either a context extension object,
960 // the global object, or the subject of a with. Try to delete it 957 // the global object, or the subject of a with. Try to delete it
961 // (respecting DONT_DELETE). 958 // (respecting DONT_DELETE).
962 Handle<JSReceiver> object = Handle<JSReceiver>::cast(holder); 959 Handle<JSReceiver> object = Handle<JSReceiver>::cast(holder);
963 Maybe<bool> result = JSReceiver::DeleteProperty(object, name); 960 Maybe<bool> result = JSReceiver::DeleteProperty(object, name);
964 MAYBE_RETURN(result, isolate->heap()->exception()); 961 MAYBE_RETURN(result, isolate->heap()->exception());
965 return isolate->heap()->ToBoolean(result.FromJust()); 962 return isolate->heap()->ToBoolean(result.FromJust());
966 } 963 }
967 964
968 965
969 static Object* ComputeReceiverForNonGlobal(Isolate* isolate, JSObject* holder) { 966 namespace {
970 DCHECK(!holder->IsJSGlobalObject());
971 967
972 // If the holder isn't a context extension object, we just return it 968 MaybeHandle<Object> LoadLookupSlot(Handle<String> name,
973 // as the receiver. This allows arguments objects to be used as 969 Object::ShouldThrow should_throw,
974 // receivers, but only if they are put in the context scope chain 970 Handle<Object>* receiver_return = nullptr) {
975 // explicitly via a with-statement. 971 Isolate* const isolate = name->GetIsolate();
976 if (holder->map()->instance_type() != JS_CONTEXT_EXTENSION_OBJECT_TYPE) {
977 return holder;
978 }
979 // Fall back to using the global object as the implicit receiver if
980 // the property turns out to be a local variable allocated in a
981 // context extension object - introduced via eval.
982 return isolate->heap()->undefined_value();
983 }
984
985
986 static ObjectPair LoadLookupSlotHelper(Arguments args, Isolate* isolate,
987 bool throw_error) {
988 HandleScope scope(isolate);
989 DCHECK_EQ(2, args.length());
990
991 if (!args[0]->IsContext() || !args[1]->IsString()) {
992 return MakePair(isolate->ThrowIllegalOperation(), NULL);
993 }
994 Handle<Context> context = args.at<Context>(0);
995 Handle<String> name = args.at<String>(1);
996 972
997 int index; 973 int index;
998 PropertyAttributes attributes; 974 PropertyAttributes attributes;
999 ContextLookupFlags flags = FOLLOW_CHAINS; 975 BindingFlags flags;
1000 BindingFlags binding_flags; 976 Handle<Object> holder = isolate->context()->Lookup(
1001 Handle<Object> holder = 977 name, FOLLOW_CHAINS, &index, &attributes, &flags);
1002 context->Lookup(name, flags, &index, &attributes, &binding_flags); 978 if (isolate->has_pending_exception()) return MaybeHandle<Object>();
1003 if (isolate->has_pending_exception()) {
1004 return MakePair(isolate->heap()->exception(), NULL);
1005 }
1006 979
1007 if (index != Context::kNotFound) { 980 if (index != Context::kNotFound) {
1008 DCHECK(holder->IsContext()); 981 DCHECK(holder->IsContext());
1009 // If the "property" we were looking for is a local variable, the 982 // If the "property" we were looking for is a local variable, the
1010 // receiver is the global object; see ECMA-262, 3rd., 10.1.6 and 10.2.3. 983 // receiver is the global object; see ECMA-262, 3rd., 10.1.6 and 10.2.3.
1011 Handle<Object> receiver = isolate->factory()->undefined_value(); 984 Handle<Object> receiver = isolate->factory()->undefined_value();
1012 Object* value = Context::cast(*holder)->get(index); 985 Handle<Object> value = handle(Context::cast(*holder)->get(index), isolate);
1013 // Check for uninitialized bindings. 986 // Check for uninitialized bindings.
1014 switch (binding_flags) { 987 switch (flags) {
1015 case MUTABLE_CHECK_INITIALIZED: 988 case MUTABLE_CHECK_INITIALIZED:
1016 case IMMUTABLE_CHECK_INITIALIZED_HARMONY: 989 case IMMUTABLE_CHECK_INITIALIZED_HARMONY:
1017 if (value->IsTheHole()) { 990 if (value->IsTheHole()) {
1018 Handle<Object> error = isolate->factory()->NewReferenceError( 991 THROW_NEW_ERROR(isolate,
1019 MessageTemplate::kNotDefined, name); 992 NewReferenceError(MessageTemplate::kNotDefined, name),
1020 isolate->Throw(*error); 993 Object);
1021 return MakePair(isolate->heap()->exception(), NULL); 994 }
995 // FALLTHROUGH
996 case IMMUTABLE_CHECK_INITIALIZED:
997 if (value->IsTheHole()) {
998 DCHECK(attributes & READ_ONLY);
999 value = isolate->factory()->undefined_value();
1022 } 1000 }
1023 // FALLTHROUGH 1001 // FALLTHROUGH
1024 case MUTABLE_IS_INITIALIZED: 1002 case MUTABLE_IS_INITIALIZED:
1025 case IMMUTABLE_IS_INITIALIZED: 1003 case IMMUTABLE_IS_INITIALIZED:
1026 case IMMUTABLE_IS_INITIALIZED_HARMONY: 1004 case IMMUTABLE_IS_INITIALIZED_HARMONY:
1027 DCHECK(!value->IsTheHole()); 1005 DCHECK(!value->IsTheHole());
1028 return MakePair(value, *receiver); 1006 if (receiver_return) *receiver_return = receiver;
1029 case IMMUTABLE_CHECK_INITIALIZED: 1007 return value;
1030 if (value->IsTheHole()) {
1031 DCHECK((attributes & READ_ONLY) != 0);
1032 value = isolate->heap()->undefined_value();
1033 }
1034 return MakePair(value, *receiver);
1035 case MISSING_BINDING: 1008 case MISSING_BINDING:
1036 UNREACHABLE(); 1009 break;
1037 return MakePair(NULL, NULL);
1038 } 1010 }
1011 UNREACHABLE();
1039 } 1012 }
1040 1013
1041 // Otherwise, if the slot was found the holder is a context extension 1014 // Otherwise, if the slot was found the holder is a context extension
1042 // object, subject of a with, or a global object. We read the named 1015 // object, subject of a with, or a global object. We read the named
1043 // property from it. 1016 // property from it.
1044 if (!holder.is_null()) { 1017 if (!holder.is_null()) {
1045 Handle<JSReceiver> object = Handle<JSReceiver>::cast(holder);
1046 // GetProperty below can cause GC.
1047 Handle<Object> receiver_handle(
1048 object->IsJSGlobalObject()
1049 ? Object::cast(isolate->heap()->undefined_value())
1050 : object->IsJSProxy() ? static_cast<Object*>(*object)
1051 : ComputeReceiverForNonGlobal(
1052 isolate, JSObject::cast(*object)),
1053 isolate);
1054
1055 // No need to unhole the value here. This is taken care of by the 1018 // No need to unhole the value here. This is taken care of by the
1056 // GetProperty function. 1019 // GetProperty function.
1057 Handle<Object> value; 1020 Handle<Object> value;
1058 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 1021 ASSIGN_RETURN_ON_EXCEPTION(
1059 isolate, value, Object::GetProperty(object, name), 1022 isolate, value, Object::GetProperty(holder, name),
1060 MakePair(isolate->heap()->exception(), NULL)); 1023 Object);
1061 return MakePair(*value, *receiver_handle); 1024 if (receiver_return) {
1025 *receiver_return =
1026 (holder->IsJSGlobalObject() || holder->IsJSContextExtensionObject())
1027 ? Handle<Object>::cast(isolate->factory()->undefined_value())
1028 : holder;
1029 }
1030 return value;
1062 } 1031 }
1063 1032
1064 if (throw_error) { 1033 if (should_throw == Object::THROW_ON_ERROR) {
1065 // The property doesn't exist - throw exception. 1034 // The property doesn't exist - throw exception.
1066 Handle<Object> error = isolate->factory()->NewReferenceError( 1035 THROW_NEW_ERROR(
1067 MessageTemplate::kNotDefined, name); 1036 isolate, NewReferenceError(MessageTemplate::kNotDefined, name), Object);
1068 isolate->Throw(*error);
1069 return MakePair(isolate->heap()->exception(), NULL);
1070 } else {
1071 // The property doesn't exist - return undefined.
1072 return MakePair(isolate->heap()->undefined_value(),
1073 isolate->heap()->undefined_value());
1074 } 1037 }
1038
1039 // The property doesn't exist - return undefined.
1040 if (receiver_return) *receiver_return = isolate->factory()->undefined_value();
1041 return isolate->factory()->undefined_value();
1042 }
1043
1044 } // namespace
1045
1046
1047 RUNTIME_FUNCTION(Runtime_LoadLookupSlot) {
1048 HandleScope scope(isolate);
1049 DCHECK_EQ(1, args.length());
1050 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
1051 Handle<Object> value;
1052 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1053 isolate, value, LoadLookupSlot(name, Object::THROW_ON_ERROR));
1054 return *value;
1075 } 1055 }
1076 1056
1077 1057
1078 RUNTIME_FUNCTION_RETURN_PAIR(Runtime_LoadLookupSlot) { 1058 RUNTIME_FUNCTION(Runtime_LoadLookupSlotInsideTypeof) {
1079 return LoadLookupSlotHelper(args, isolate, true); 1059 HandleScope scope(isolate);
1060 DCHECK_EQ(1, args.length());
1061 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
1062 Handle<Object> value;
1063 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1064 isolate, value, LoadLookupSlot(name, Object::DONT_THROW));
1065 return *value;
1080 } 1066 }
1081 1067
1082 1068
1083 RUNTIME_FUNCTION_RETURN_PAIR(Runtime_LoadLookupSlotNoReferenceError) { 1069 RUNTIME_FUNCTION_RETURN_PAIR(Runtime_LoadLookupSlotForCall) {
1084 return LoadLookupSlotHelper(args, isolate, false); 1070 HandleScope scope(isolate);
1071 DCHECK_EQ(1, args.length());
1072 DCHECK(args[0]->IsString());
1073 Handle<String> name = args.at<String>(0);
1074 Handle<Object> value;
1075 Handle<Object> receiver;
1076 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1077 isolate, value, LoadLookupSlot(name, Object::THROW_ON_ERROR, &receiver),
1078 MakePair(isolate->heap()->exception(), nullptr));
1079 return MakePair(*value, *receiver);
1085 } 1080 }
1086 1081
1087 1082
1088 RUNTIME_FUNCTION(Runtime_StoreLookupSlot) { 1083 namespace {
1089 HandleScope scope(isolate);
1090 DCHECK(args.length() == 4);
1091 1084
1092 CONVERT_ARG_HANDLE_CHECKED(Object, value, 0); 1085 MaybeHandle<Object> StoreLookupSlot(Handle<String> name, Handle<Object> value,
1093 CONVERT_ARG_HANDLE_CHECKED(Context, context, 1); 1086 LanguageMode language_mode) {
1094 CONVERT_ARG_HANDLE_CHECKED(String, name, 2); 1087 Isolate* const isolate = name->GetIsolate();
1095 CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 3); 1088 Handle<Context> context(isolate->context(), isolate);
1096 1089
1097 int index; 1090 int index;
1098 PropertyAttributes attributes; 1091 PropertyAttributes attributes;
1099 ContextLookupFlags flags = FOLLOW_CHAINS; 1092 BindingFlags flags;
1100 BindingFlags binding_flags;
1101 Handle<Object> holder = 1093 Handle<Object> holder =
1102 context->Lookup(name, flags, &index, &attributes, &binding_flags); 1094 context->Lookup(name, FOLLOW_CHAINS, &index, &attributes, &flags);
1103 if (holder.is_null()) { 1095 if (holder.is_null()) {
1104 // In case of JSProxy, an exception might have been thrown. 1096 // In case of JSProxy, an exception might have been thrown.
1105 if (isolate->has_pending_exception()) return isolate->heap()->exception(); 1097 if (isolate->has_pending_exception()) return MaybeHandle<Object>();
1106 } 1098 }
1107 1099
1108 // The property was found in a context slot. 1100 // The property was found in a context slot.
1109 if (index != Context::kNotFound) { 1101 if (index != Context::kNotFound) {
1110 if ((binding_flags == MUTABLE_CHECK_INITIALIZED || 1102 if ((flags == MUTABLE_CHECK_INITIALIZED ||
1111 binding_flags == IMMUTABLE_CHECK_INITIALIZED_HARMONY) && 1103 flags == IMMUTABLE_CHECK_INITIALIZED_HARMONY) &&
1112 Handle<Context>::cast(holder)->is_the_hole(index)) { 1104 Handle<Context>::cast(holder)->is_the_hole(index)) {
1113 THROW_NEW_ERROR_RETURN_FAILURE( 1105 THROW_NEW_ERROR(isolate,
1114 isolate, NewReferenceError(MessageTemplate::kNotDefined, name)); 1106 NewReferenceError(MessageTemplate::kNotDefined, name),
1107 Object);
1115 } 1108 }
1116 if ((attributes & READ_ONLY) == 0) { 1109 if ((attributes & READ_ONLY) == 0) {
1117 Handle<Context>::cast(holder)->set(index, *value); 1110 Handle<Context>::cast(holder)->set(index, *value);
1118 } else if (is_strict(language_mode)) { 1111 } else if (is_strict(language_mode)) {
1119 // Setting read only property in strict mode. 1112 // Setting read only property in strict mode.
1120 THROW_NEW_ERROR_RETURN_FAILURE( 1113 THROW_NEW_ERROR(isolate,
1121 isolate, NewTypeError(MessageTemplate::kStrictCannotAssign, name)); 1114 NewTypeError(MessageTemplate::kStrictCannotAssign, name),
1115 Object);
1122 } 1116 }
1123 return *value; 1117 return value;
1124 } 1118 }
1125 1119
1126 // Slow case: The property is not in a context slot. It is either in a 1120 // Slow case: The property is not in a context slot. It is either in a
1127 // context extension object, a property of the subject of a with, or a 1121 // context extension object, a property of the subject of a with, or a
1128 // property of the global object. 1122 // property of the global object.
1129 Handle<JSReceiver> object; 1123 Handle<JSReceiver> object;
1130 if (attributes != ABSENT) { 1124 if (attributes != ABSENT) {
1131 // The property exists on the holder. 1125 // The property exists on the holder.
1132 object = Handle<JSReceiver>::cast(holder); 1126 object = Handle<JSReceiver>::cast(holder);
1133 } else if (is_strict(language_mode)) { 1127 } else if (is_strict(language_mode)) {
1134 // If absent in strict mode: throw. 1128 // If absent in strict mode: throw.
1135 THROW_NEW_ERROR_RETURN_FAILURE( 1129 THROW_NEW_ERROR(
1136 isolate, NewReferenceError(MessageTemplate::kNotDefined, name)); 1130 isolate, NewReferenceError(MessageTemplate::kNotDefined, name), Object);
1137 } else { 1131 } else {
1138 // If absent in sloppy mode: add the property to the global object. 1132 // If absent in sloppy mode: add the property to the global object.
1139 object = Handle<JSReceiver>(context->global_object()); 1133 object = Handle<JSReceiver>(context->global_object());
1140 } 1134 }
1141 1135
1142 RETURN_FAILURE_ON_EXCEPTION( 1136 ASSIGN_RETURN_ON_EXCEPTION(
1143 isolate, Object::SetProperty(object, name, value, language_mode)); 1137 isolate, value, Object::SetProperty(object, name, value, language_mode),
1138 Object);
1139 return value;
1140 }
1144 1141
1142 } // namespace
1143
1144
1145 RUNTIME_FUNCTION(Runtime_StoreLookupSlot_Sloppy) {
1146 HandleScope scope(isolate);
1147 DCHECK_EQ(2, args.length());
1148 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
1149 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
1150 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value,
1151 StoreLookupSlot(name, value, SLOPPY));
1145 return *value; 1152 return *value;
1146 } 1153 }
1147 1154
1155
1156 RUNTIME_FUNCTION(Runtime_StoreLookupSlot_Strict) {
1157 HandleScope scope(isolate);
1158 DCHECK_EQ(2, args.length());
1159 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
1160 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
1161 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value,
1162 StoreLookupSlot(name, value, STRICT));
1163 return *value;
1164 }
1165
1148 1166
1149 RUNTIME_FUNCTION(Runtime_ArgumentsLength) { 1167 RUNTIME_FUNCTION(Runtime_ArgumentsLength) {
1150 HandleScope scope(isolate); 1168 HandleScope scope(isolate);
1151 DCHECK(args.length() == 0); 1169 DCHECK(args.length() == 0);
1152 int argument_count = 0; 1170 int argument_count = 0;
1153 GetCallerArguments(isolate, &argument_count); 1171 GetCallerArguments(isolate, &argument_count);
1154 return Smi::FromInt(argument_count); 1172 return Smi::FromInt(argument_count);
1155 } 1173 }
1156 1174
1157 1175
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
1223 1241
1224 // Lookup in the initial Object.prototype object. 1242 // Lookup in the initial Object.prototype object.
1225 Handle<Object> result; 1243 Handle<Object> result;
1226 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 1244 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1227 isolate, result, 1245 isolate, result,
1228 Object::GetProperty(isolate->initial_object_prototype(), key)); 1246 Object::GetProperty(isolate->initial_object_prototype(), key));
1229 return *result; 1247 return *result;
1230 } 1248 }
1231 } // namespace internal 1249 } // namespace internal
1232 } // namespace v8 1250 } // namespace v8
OLDNEW
« no previous file with comments | « src/runtime/runtime.h ('k') | test/cctest/interpreter/test-bytecode-generator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698