Index: src/runtime.cc |
diff --git a/src/runtime.cc b/src/runtime.cc |
index 7eb753ab1c9d36f6848efb21f6d7b4f83ae05fa6..0f8d79406739ac5d45479c398a24cfc06f78df3e 100644 |
--- a/src/runtime.cc |
+++ b/src/runtime.cc |
@@ -9782,6 +9782,59 @@ bool CodeGenerationFromStringsAllowed(Isolate* isolate, |
} |
+// Walk up the stack expecting: |
+// - Runtime_CompileString |
+// - JSFunction callee (eval, Function constructor, etc) |
+// - call() (maybe) |
+// - apply() (maybe) |
+// - bind() (maybe) |
+// - JSFunction caller (maybe) |
+// |
+// return true if the caller has the same security token as the callee |
+// or if an exit frame was hit, in which case allow it through, as it could |
+// have come through the api. |
+static bool TokensMatchForCompileString(Isolate* isolate) { |
+ MaybeHandle<JSFunction> callee; |
+ bool exit_handled = true; |
+ bool tokens_match = true; |
+ bool done = false; |
+ for (StackFrameIterator it(isolate); !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(); |
+ // Capture the callee function. |
+ if (callee.is_null()) { |
+ callee = fun; |
+ exit_handled = true; |
+ continue; |
+ } |
+ // Exit condition. |
+ Handle<Context> context(callee.ToHandleChecked()->context()); |
+ if (!fun->context()->HasSameSecurityTokenAs(*context)) { |
+ tokens_match = false; |
+ done = true; |
+ continue; |
+ } |
+ // Skip bound functions in correct origin. |
+ if (fun->shared()->bound()) { |
+ exit_handled = true; |
+ continue; |
+ } |
+ done = true; |
+ } |
+ } |
+ return !exit_handled || tokens_match; |
+} |
+ |
+ |
RUNTIME_FUNCTION(Runtime_CompileString) { |
HandleScope scope(isolate); |
ASSERT(args.length() == 2); |
@@ -9791,6 +9844,11 @@ RUNTIME_FUNCTION(Runtime_CompileString) { |
// Extract native context. |
Handle<Context> context(isolate->context()->native_context()); |
+ // Filter cross security context calls. |
+ if (!TokensMatchForCompileString(isolate)) { |
+ return isolate->heap()->undefined_value(); |
+ } |
+ |
// Check if native context allows code generation from |
// strings. Throw an exception if it doesn't. |
if (context->allow_code_gen_from_strings()->IsFalse() && |