Index: src/builtins.cc |
diff --git a/src/builtins.cc b/src/builtins.cc |
index 07817fe8c0899444decbddebeb73acd90d6a5e6c..6e604ed5e9a9f13bb6c6db7ac932005a35b4b30c 100644 |
--- a/src/builtins.cc |
+++ b/src/builtins.cc |
@@ -4102,8 +4102,48 @@ void Builtins::Generate_DatePrototypeGetUTCSeconds(MacroAssembler* masm) { |
namespace { |
+// Walk up the stack expecting: |
+// - ExitFrame |
+// - call() (maybe) |
+// - apply() (maybe) |
+// - bind() (maybe) |
+// - JSFunction caller (maybe) |
+// |
+// return true if the caller has access to the callee or if an exit frame was |
+// hit, in which case allow it through, as it could have come through the api. |
+bool HasAccessToContextForCreateDynamicFunction( |
+ Isolate* isolate, Handle<JSObject> target_global_proxy) { |
+ bool exit_handled = true; |
+ bool has_access = true; |
+ bool done = false; |
+ StackFrameIterator it(isolate); |
+ // Skip exit frame that corresponds to the builtin call. |
+ it.Advance(); |
+ for (; !it.done() && !done; it.Advance()) { |
+ StackFrame* raw_frame = it.frame(); |
+ if (!raw_frame->is_java_script()) { |
+ if (raw_frame->is_exit()) exit_handled = false; |
+ continue; |
+ } |
+ JavaScriptFrame* outer_frame = JavaScriptFrame::cast(raw_frame); |
+ List<FrameSummary> frames(FLAG_max_inlining_levels + 1); |
+ outer_frame->Summarize(&frames); |
+ for (int i = frames.length() - 1; i >= 0 && !done; --i) { |
+ FrameSummary& frame = frames[i]; |
+ Handle<JSFunction> fun = frame.function(); |
+ if (!isolate->MayAccess(handle(fun->context()), target_global_proxy)) { |
+ has_access = false; |
+ done = true; |
+ continue; |
+ } |
+ done = true; |
+ } |
+ } |
+ return !exit_handled || has_access; |
+} |
+ |
// ES6 section 19.2.1.1.1 CreateDynamicFunction |
-MaybeHandle<JSFunction> CreateDynamicFunction( |
+MaybeHandle<Object> CreateDynamicFunction( |
Isolate* isolate, |
BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget> args, |
const char* token) { |
@@ -4111,6 +4151,15 @@ MaybeHandle<JSFunction> CreateDynamicFunction( |
DCHECK_LE(1, args.length()); |
int const argc = args.length() - 1; |
+ Handle<JSFunction> target = args.target<JSFunction>(); |
+ Handle<JSObject> target_global_proxy(target->global_proxy(), isolate); |
+ |
+ if (!HasAccessToContextForCreateDynamicFunction(isolate, |
+ target_global_proxy)) { |
+ isolate->CountUsage(v8::Isolate::kFunctionConstructorReturnedUndefined); |
+ return isolate->factory()->undefined_value(); |
+ } |
+ |
// Build the source string. |
Handle<String> source; |
{ |
@@ -4125,7 +4174,7 @@ MaybeHandle<JSFunction> CreateDynamicFunction( |
Handle<String> param; |
ASSIGN_RETURN_ON_EXCEPTION( |
isolate, param, Object::ToString(isolate, args.at<Object>(i)), |
- JSFunction); |
+ Object); |
param = String::Flatten(param); |
builder.AppendString(param); |
// If the formal parameters string include ) - an illegal |
@@ -4150,37 +4199,35 @@ MaybeHandle<JSFunction> CreateDynamicFunction( |
Handle<String> body; |
ASSIGN_RETURN_ON_EXCEPTION( |
isolate, body, Object::ToString(isolate, args.at<Object>(argc)), |
- JSFunction); |
+ Object); |
builder.AppendString(body); |
} |
builder.AppendCString("\n})"); |
- ASSIGN_RETURN_ON_EXCEPTION(isolate, source, builder.Finish(), JSFunction); |
+ ASSIGN_RETURN_ON_EXCEPTION(isolate, source, builder.Finish(), Object); |
// The SyntaxError must be thrown after all the (observable) ToString |
// conversions are done. |
if (parenthesis_in_arg_string) { |
THROW_NEW_ERROR(isolate, |
NewSyntaxError(MessageTemplate::kParenthesisInArgString), |
- JSFunction); |
+ Object); |
} |
} |
// Compile the string in the constructor and not a helper so that errors to |
// come from here. |
- Handle<JSFunction> target = args.target<JSFunction>(); |
- Handle<JSObject> target_global_proxy(target->global_proxy(), isolate); |
Handle<JSFunction> function; |
{ |
ASSIGN_RETURN_ON_EXCEPTION( |
isolate, function, |
CompileString(handle(target->native_context(), isolate), source, |
ONLY_SINGLE_FUNCTION_LITERAL), |
- JSFunction); |
+ Object); |
Handle<Object> result; |
ASSIGN_RETURN_ON_EXCEPTION( |
isolate, result, |
Execution::Call(isolate, function, target_global_proxy, 0, nullptr), |
- JSFunction); |
+ Object); |
function = Handle<JSFunction>::cast(result); |
function->shared()->set_name_should_print_as_anonymous(true); |
} |
@@ -4199,7 +4246,7 @@ MaybeHandle<JSFunction> CreateDynamicFunction( |
Handle<Map> initial_map; |
ASSIGN_RETURN_ON_EXCEPTION( |
isolate, initial_map, |
- JSFunction::GetDerivedMap(isolate, target, new_target), JSFunction); |
+ JSFunction::GetDerivedMap(isolate, target, new_target), Object); |
Handle<SharedFunctionInfo> shared_info(function->shared(), isolate); |
Handle<Map> map = Map::AsLanguageMode( |
@@ -4218,7 +4265,7 @@ MaybeHandle<JSFunction> CreateDynamicFunction( |
// ES6 section 19.2.1.1 Function ( p1, p2, ... , pn, body ) |
BUILTIN(FunctionConstructor) { |
HandleScope scope(isolate); |
- Handle<JSFunction> result; |
+ Handle<Object> result; |
ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
isolate, result, CreateDynamicFunction(isolate, args, "function")); |
return *result; |