thanks. But in Modification Two, I changed object x 's property a in a different context successfully. is this fulfilled "Access checks are invoked when trying to access objects" condition?
在 2018年5月30日星期三 UTC+8下午5:32:55,Ben Noordhuis写道: > > On Wed, May 30, 2018 at 9:32 AM, <fengx...@gmail.com <javascript:>> > wrote: > > I try to understand SetSecurityToken's function. So I modified > > EvalInAccessCheckedContext test case in test-api.cc which is included in > v8 > > sourcecode. Follow is my modification. > > > > Modification One: > > > > TEST(EvalInAccessCheckedContext) { > > v8::Isolate* isolate = CcTest::isolate(); > > v8::HandleScope scope(isolate); > > > > v8::Local<v8::ObjectTemplate> obj_template = > > v8::ObjectTemplate::New(isolate); > > > > //obj_template->SetAccessCheckCallback(AccessAlwaysAllowed); //comment > > this line to ensure cross access only be controlled by SetSecurityToken > > > > 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::Local<v8::Value> fun = CompileRun( > > "var x = 42;" > > "(function() {" > > " var e = eval;" > > //" return function(s) { return e(s); }" // this line will fail > test > > because SecurityToken is not the same > > " return function(s) { return eval(s); }" // this line will pass > > test. but why? > > "})()"); > > 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(context1, v8_str("fun"), fun).FromJust(); > > v8::Local<v8::Value> x_value = CompileRun("fun('x')"); > > CHECK_EQ(42, x_value->Int32Value(context1).FromJust()); > > context1->Exit(); > > } > > > > > > Modification Two: > > > > TEST(EvalInAccessCheckedContext) { > > v8::Isolate* isolate = CcTest::isolate(); > > v8::HandleScope scope(isolate); > > > > v8::Local<v8::ObjectTemplate> obj_template = > > v8::ObjectTemplate::New(isolate); > > > > //obj_template->SetAccessCheckCallback(AccessAlwaysAllowed); //comment > > this line to ensure cross access only be controlled by SetSecurityToken > > > > 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::Local<v8::Value> fun = CompileRun( > > "var x = {a:42};" > > "(function() {" > > " var e = eval;" > > " return function(s) { return x; }" // just return a object > that's > > defined in context0 > > "})()"); > > > > v8::Local<v8::Value> x_value0 = CompileRun("x.a"); > > CHECK_EQ(42, x_value0->Int32Value(context0).FromJust()); > > > > Local<v8::Object> obj = context0->Global()->Get(context0, > > v8_str("x")).ToLocalChecked()->ToObject(); > > obj->Set(context0, v8_str("a"), > v8::Integer::New(context0->GetIsolate(), > > 100)).FromJust(); > > context0->Global()->Set(context0, v8_str("fun"), fun).FromJust(); > > v8::Local<v8::Value> x_value00 = CompileRun("fun('x')"); > > CHECK_EQ(100, x_value00->ToObject()->Get(context0, > > v8_str("a")).ToLocalChecked()->Int32Value(context0).FromJust()); > > > > 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(context1, v8_str("fun"), fun).FromJust(); > > v8::Local<v8::Value> x_value = CompileRun("fun('x')"); > > CHECK_EQ(100, x_value->ToObject()->Get(context1, > > v8_str("a")).ToLocalChecked()->Int32Value(context1).FromJust()); > > > > x_value->ToObject()->Set(context1, v8_str("a"), > > v8::Integer::New(context0->GetIsolate(), 102)).FromJust();// change x > object > > of context0 in context1 > > context1->Exit(); > > > > context0->Enter(); > > { > > Local<v8::Object> obj = context0->Global()->Get(context0, > > v8_str("x")).ToLocalChecked()->ToObject(); > > CHECK_EQ(102, obj->Get(context0, > > v8_str("a")).ToLocalChecked()->Int32Value(context0).FromJust()); // this > > will pass. so why change is allowed? > > > > v8::Local<v8::Value> x_value00 = CompileRun("fun('x')"); > > CHECK_EQ(102, x_value00->ToObject()->Get(context0, > > v8_str("a")).ToLocalChecked()->Int32Value(context0).FromJust()); > > } > > context0->Exit(); > > } > > Is your question why direct eval() works but indirect eval() doesn't > with different security tokens? > > It's because direct eval() isn't really a function, it's closer to a > keyword. It has to be because of its runtime semantics of evaluating > the string in the context of the surrounding code. Indirect eval() > however is a regular function that is subject to access checks. > > Access checks are invoked when trying to access objects. Context A > can pass on objects from context B as long as it doesn't access it, > where access = read or write properties, invoke the [[Call]] operation > of function objects, etc. > -- -- v8-users mailing list v8-users@googlegroups.com http://groups.google.com/group/v8-users --- You received this message because you are subscribed to the Google Groups "v8-users" group. To unsubscribe from this group and stop receiving emails from it, send an email to v8-users+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.