Commit fe6ff652 authored by machenbach's avatar machenbach Committed by Commit bot

Revert of Don't compile functions in a context the caller doesn't have access...

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}
parent d515e513
......@@ -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());
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment