Revert of Don't compile functions in a context the caller doesn't have access to (patchset #1 id:1 of https://codereview.chromium.org/1393713006/ )
Reason for revert: [Sheriff] Breaks layout tests. Please add needsmanualrebaseline upstream first if intended. E.g.: http://build.chromium.org/p/client.v8.fyi/builders/V8-Blink%20Linux%2064/builds/2263 (one of them is a timeout that only happens with this commit) Original issue's description: > Don't compile functions in a context the caller doesn't have access to > > Instead, just return undefined. > > A side effect of this is that it's no longer possible to compile > functions in a detached context. > > Based on https://codereview.chromium.org/294073002 but taking access > check callbacks into account > > BUG=chromium:541703 > R=verwaest@chromium.org > LOG=y > > Committed: https://crrev.com/9a5e2f512c4aa90563eb575605c2a8c2a92ac9f4 > Cr-Commit-Position: refs/heads/master@{#31208} TBR=verwaest@chromium.org,jochen@chromium.org NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=chromium:541703 Review URL: https://codereview.chromium.org/1395583004 Cr-Commit-Position: refs/heads/master@{#31212}
This commit is contained in:
parent
d515e5138d
commit
fe6ff6523e
14
src/d8.cc
14
src/d8.cc
@ -140,17 +140,6 @@ Worker* GetWorkerFromInternalField(Isolate* isolate, Local<Object> object) {
|
||||
#endif // !V8_SHARED
|
||||
|
||||
|
||||
bool NamedAccessCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key,
|
||||
v8::AccessType type, v8::Local<v8::Value> data) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool IndexedAccessCheck(v8::Local<v8::Object> host, uint32_t index,
|
||||
v8::AccessType type, v8::Local<v8::Value> data) {
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
@ -1189,9 +1178,6 @@ Local<ObjectTemplate> Shell::CreateGlobalTemplate(Isolate* isolate) {
|
||||
.ToLocalChecked(),
|
||||
os_templ);
|
||||
|
||||
global_template->SetAccessCheckCallbacks(NamedAccessCheck,
|
||||
IndexedAccessCheck);
|
||||
|
||||
return global_template;
|
||||
}
|
||||
|
||||
|
@ -80,9 +80,7 @@ function GeneratorFunctionConstructor(arg1) { // length == 1
|
||||
var global_proxy = %GlobalProxy(GeneratorFunctionConstructor);
|
||||
// Compile the string in the constructor and not a helper so that errors
|
||||
// appear to come from here.
|
||||
var f = %CompileString(source, true);
|
||||
if (!IS_FUNCTION(f)) return f;
|
||||
f = %_CallFunction(global_proxy, f);
|
||||
var f = %_CallFunction(global_proxy, %CompileString(source, true));
|
||||
%FunctionMarkNameShouldPrintAsAnonymous(f);
|
||||
return f;
|
||||
}
|
||||
|
@ -352,59 +352,6 @@ 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 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 HasAccessToContextForCompileString(Isolate* isolate) {
|
||||
MaybeHandle<JSFunction> callee;
|
||||
bool exit_handled = true;
|
||||
bool has_access = 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<JSObject> callee_global_proxy(
|
||||
callee.ToHandleChecked()->context()->global_proxy());
|
||||
if (!isolate->MayAccess(handle(fun->context()), callee_global_proxy)) {
|
||||
has_access = false;
|
||||
done = true;
|
||||
continue;
|
||||
}
|
||||
// Skip bound functions in correct origin.
|
||||
if (fun->shared()->bound()) {
|
||||
exit_handled = true;
|
||||
continue;
|
||||
}
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
return !exit_handled || has_access;
|
||||
}
|
||||
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_CompileString) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK(args.length() == 2);
|
||||
@ -414,11 +361,6 @@ RUNTIME_FUNCTION(Runtime_CompileString) {
|
||||
// Extract native context.
|
||||
Handle<Context> context(isolate->native_context());
|
||||
|
||||
// Filter cross security context calls.
|
||||
if (!HasAccessToContextForCompileString(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() &&
|
||||
|
@ -1779,9 +1779,7 @@ function FunctionConstructor(arg1) { // length == 1
|
||||
var global_proxy = %GlobalProxy(FunctionConstructor);
|
||||
// Compile the string in the constructor and not a helper so that errors
|
||||
// appear to come from here.
|
||||
var f = %CompileString(source, true);
|
||||
if (!IS_FUNCTION(f)) return f;
|
||||
f = %_CallFunction(global_proxy, f);
|
||||
var f = %_CallFunction(global_proxy, %CompileString(source, true));
|
||||
%FunctionMarkNameShouldPrintAsAnonymous(f);
|
||||
return f;
|
||||
}
|
||||
|
@ -8741,13 +8741,6 @@ static bool AccessAlwaysBlocked(Local<v8::Object> global, Local<Value> name,
|
||||
}
|
||||
|
||||
|
||||
static bool AccessAlwaysAllowed(Local<v8::Object> global, Local<Value> name,
|
||||
v8::AccessType type, Local<Value> data) {
|
||||
i::PrintF("Access allowed.\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
THREADED_TEST(AccessControlGetOwnPropertyNames) {
|
||||
v8::Isolate* isolate = CcTest::isolate();
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
@ -9987,7 +9980,7 @@ THREADED_TEST(EvalInDetachedGlobal) {
|
||||
context0->DetachGlobal();
|
||||
v8::TryCatch catcher(isolate);
|
||||
x_value = CompileRun("fun('x')");
|
||||
CHECK(x_value->IsUndefined());
|
||||
CHECK_EQ(42, x_value->Int32Value());
|
||||
context1->Exit();
|
||||
}
|
||||
|
||||
@ -21953,71 +21946,3 @@ TEST(ArrayIteratorMethods) {
|
||||
ExpectString("typeof values", "function");
|
||||
ExpectString("typeof entries", "function");
|
||||
}
|
||||
|
||||
|
||||
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(result->IsInt32());
|
||||
CHECK_EQ(1, result->Int32Value());
|
||||
}
|
||||
|
||||
|
||||
TEST(EvalInAccessCheckedContext) {
|
||||
v8::Isolate* isolate = CcTest::isolate();
|
||||
v8::HandleScope scope(isolate);
|
||||
|
||||
v8::Handle<v8::ObjectTemplate> obj_template =
|
||||
v8::ObjectTemplate::New(isolate);
|
||||
|
||||
obj_template->SetAccessCheckCallbacks(AccessAlwaysAllowed, NULL);
|
||||
|
||||
v8::Local<Context> context0 = Context::New(isolate, NULL, obj_template);
|
||||
v8::Local<Context> context1 = Context::New(isolate, NULL, obj_template);
|
||||
|
||||
Local<Value> foo = v8_str("foo");
|
||||
Local<Value> bar = v8_str("bar");
|
||||
|
||||
// Set to different domains.
|
||||
context0->SetSecurityToken(foo);
|
||||
context1->SetSecurityToken(bar);
|
||||
|
||||
// Set up function in context0 that uses eval from context0.
|
||||
context0->Enter();
|
||||
v8::Handle<v8::Value> fun = CompileRun(
|
||||
"var x = 42;"
|
||||
"(function() {"
|
||||
" var e = eval;"
|
||||
" return function(s) { return e(s); }"
|
||||
"})()");
|
||||
context0->Exit();
|
||||
|
||||
// Put the function into context1 and call it. Since the access check
|
||||
// callback always returns true, the call succeeds even though the tokens
|
||||
// are different.
|
||||
context1->Enter();
|
||||
context1->Global()->Set(v8_str("fun"), fun);
|
||||
v8::Handle<v8::Value> x_value = CompileRun("fun('x')");
|
||||
CHECK_EQ(42, x_value->Int32Value());
|
||||
context1->Exit();
|
||||
}
|
||||
|
@ -88,68 +88,3 @@ o = Realm.eval(realmIndex, "new f()");
|
||||
proto = Object.getPrototypeOf(o);
|
||||
assertFalse(proto === Object.prototype);
|
||||
assertTrue(proto === otherObject.prototype);
|
||||
|
||||
|
||||
// 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());
|
||||
|
Loading…
Reference in New Issue
Block a user