Revision: 21793
Author: [email protected]
Date: Thu Jun 12 08:28:19 2014 UTC
Log: filter cross context eval
[email protected]
BUG=
Review URL: https://codereview.chromium.org/294073002
http://code.google.com/p/v8/source/detail?r=21793
Modified:
/branches/bleeding_edge/src/generator.js
/branches/bleeding_edge/src/runtime.cc
/branches/bleeding_edge/src/v8natives.js
/branches/bleeding_edge/test/cctest/test-api.cc
/branches/bleeding_edge/test/mjsunit/cross-realm-filtering.js
=======================================
--- /branches/bleeding_edge/src/generator.js Tue Apr 29 06:42:26 2014 UTC
+++ /branches/bleeding_edge/src/generator.js Thu Jun 12 08:28:19 2014 UTC
@@ -43,7 +43,9 @@
var global_receiver = %GlobalReceiver(global);
// Compile the string in the constructor and not a helper so that errors
// appear to come from here.
- var f = %_CallFunction(global_receiver, %CompileString(source, true));
+ var f = %CompileString(source, true);
+ if (!IS_FUNCTION(f)) return f;
+ f = %_CallFunction(global_receiver, f);
%FunctionMarkNameShouldPrintAsAnonymous(f);
return f;
}
=======================================
--- /branches/bleeding_edge/src/runtime.cc Thu Jun 12 07:38:49 2014 UTC
+++ /branches/bleeding_edge/src/runtime.cc Thu Jun 12 08:28:19 2014 UTC
@@ -9780,6 +9780,59 @@
return callback(v8::Utils::ToLocal(context));
}
}
+
+
+// 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) {
@@ -9790,6 +9843,11 @@
// 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.
=======================================
--- /branches/bleeding_edge/src/v8natives.js Fri May 23 12:55:57 2014 UTC
+++ /branches/bleeding_edge/src/v8natives.js Thu Jun 12 08:28:19 2014 UTC
@@ -1840,7 +1840,9 @@
var global_receiver = %GlobalReceiver(global);
// Compile the string in the constructor and not a helper so that errors
// appear to come from here.
- var f = %_CallFunction(global_receiver, %CompileString(source, true));
+ var f = %CompileString(source, true);
+ if (!IS_FUNCTION(f)) return f;
+ f = %_CallFunction(global_receiver, f);
%FunctionMarkNameShouldPrintAsAnonymous(f);
return f;
}
=======================================
--- /branches/bleeding_edge/test/cctest/test-api.cc Wed Jun 11 05:48:33
2014 UTC
+++ /branches/bleeding_edge/test/cctest/test-api.cc Thu Jun 12 08:28:19
2014 UTC
@@ -22714,3 +22714,29 @@
int line_number = script->GetUnboundScript()->GetLineNumber(0);
CHECK_EQ(13, line_number);
}
+
+
+Local<v8::Context> call_eval_context;
+Local<v8::Function> call_eval_bound_function;
+static void CallEval(const v8::FunctionCallbackInfo<v8::Value>& args) {
+ v8::Context::Scope scope(call_eval_context);
+ args.GetReturnValue().Set(
+ call_eval_bound_function->Call(call_eval_context->Global(), 0,
NULL));
+}
+
+
+TEST(CrossActivationEval) {
+ LocalContext env;
+ v8::Isolate* isolate = env->GetIsolate();
+ v8::HandleScope scope(isolate);
+ {
+ call_eval_context = v8::Context::New(isolate);
+ v8::Context::Scope scope(call_eval_context);
+ call_eval_bound_function =
+ Local<Function>::Cast(CompileRun("eval.bind(this, '1')"));
+ }
+ env->Global()->Set(v8_str("CallEval"),
+ v8::FunctionTemplate::New(isolate, CallEval)->GetFunction());
+ Local<Value> result = CompileRun("CallEval();");
+ CHECK_EQ(result, v8::Integer::New(isolate, 1));
+}
=======================================
--- /branches/bleeding_edge/test/mjsunit/cross-realm-filtering.js Mon May
19 13:45:45 2014 UTC
+++ /branches/bleeding_edge/test/mjsunit/cross-realm-filtering.js Thu Jun
12 08:28:19 2014 UTC
@@ -70,3 +70,72 @@
Realm.eval(realms[0], script);
assertSame(Realm.shared.caller_0, Realm.shared.result_0);
assertSame(null, Realm.shared.result_1);
+
+
+// Check function constructor.
+var ctor_script = "Function.constructor";
+var ctor_a_script =
+ "(function() { return Function.constructor.apply(this, ['return 1;']);
})";
+var ctor_b_script = "Function.constructor.bind(this, 'return 1;')";
+var ctor_c_script =
+ "(function() { return Function.constructor.call(this, 'return 1;');
})";
+Realm.shared = {
+ ctor_0 : Realm.eval(realms[0], ctor_script),
+ ctor_1 : Realm.eval(realms[1], ctor_script),
+ ctor_a_0 : Realm.eval(realms[0], ctor_a_script),
+ ctor_a_1 : Realm.eval(realms[1], ctor_a_script),
+ ctor_b_0 : Realm.eval(realms[0], ctor_b_script),
+ ctor_b_1 : Realm.eval(realms[1], ctor_b_script),
+ ctor_c_0 : Realm.eval(realms[0], ctor_c_script),
+ ctor_c_1 : Realm.eval(realms[1], ctor_c_script),
+}
+
+var script_0
= " \
+ var ctor_0 =
Realm.shared.ctor_0; \
+ Realm.shared.direct_0 = ctor_0('return
1'); \
+ Realm.shared.indirect_0 = (function() { return ctor_0('return 1;');
})(); \
+ Realm.shared.apply_0 = ctor_0.apply(this, ['return
1']); \
+ Realm.shared.bind_0 = ctor_0.bind(this, 'return
1')(); \
+ Realm.shared.call_0 = ctor_0.call(this, 'return
1'); \
+ Realm.shared.a_0 =
Realm.shared.ctor_a_0(); \
+ Realm.shared.b_0 =
Realm.shared.ctor_b_0(); \
+ Realm.shared.c_0 =
Realm.shared.ctor_c_0(); \
+";
+
+script = script_0 + script_0.replace(/_0/g, "_1");
+
+Realm.eval(realms[0], script);
+assertSame(1, Realm.shared.direct_0());
+assertSame(1, Realm.shared.indirect_0());
+assertSame(1, Realm.shared.apply_0());
+assertSame(1, Realm.shared.bind_0());
+assertSame(1, Realm.shared.call_0());
+assertSame(1, Realm.shared.a_0());
+assertSame(1, Realm.shared.b_0());
+assertSame(1, Realm.shared.c_0());
+assertSame(undefined, Realm.shared.direct_1);
+assertSame(undefined, Realm.shared.indirect_1);
+assertSame(undefined, Realm.shared.apply_1);
+assertSame(undefined, Realm.shared.bind_1);
+assertSame(undefined, Realm.shared.call_1);
+assertSame(1, Realm.shared.a_1());
+assertSame(undefined, Realm.shared.b_1);
+assertSame(1, Realm.shared.c_1());
+
+Realm.eval(realms[1], script);
+assertSame(undefined, Realm.shared.direct_0);
+assertSame(undefined, Realm.shared.indirect_0);
+assertSame(undefined, Realm.shared.apply_0);
+assertSame(undefined, Realm.shared.bind_0);
+assertSame(undefined, Realm.shared.call_0);
+assertSame(1, Realm.shared.a_0());
+assertSame(undefined, Realm.shared.b_0);
+assertSame(1, Realm.shared.c_1());
+assertSame(1, Realm.shared.direct_1());
+assertSame(1, Realm.shared.indirect_1());
+assertSame(1, Realm.shared.apply_1());
+assertSame(1, Realm.shared.bind_1());
+assertSame(1, Realm.shared.call_1());
+assertSame(1, Realm.shared.a_1());
+assertSame(1, Realm.shared.b_1());
+assertSame(1, Realm.shared.c_1());
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.