On Wed, May 30, 2018 at 9:32 AM,  <fengxing...@gmail.com> 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.

Reply via email to