Home | History | Annotate | Download | only in cctest
      1 // Copyright 2016 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include <stdlib.h>
      6 
      7 #include "test/cctest/cctest.h"
      8 
      9 namespace {
     10 
     11 int32_t g_cross_context_int = 0;
     12 
     13 void NamedGetter(v8::Local<v8::Name> property,
     14                  const v8::PropertyCallbackInfo<v8::Value>& info) {
     15   v8::Isolate* isolate = info.GetIsolate();
     16   v8::Local<v8::Context> context = isolate->GetCurrentContext();
     17   if (property->Equals(context, v8_str("cross_context_int")).FromJust())
     18     info.GetReturnValue().Set(g_cross_context_int);
     19 }
     20 
     21 void NamedSetter(v8::Local<v8::Name> property, v8::Local<v8::Value> value,
     22                  const v8::PropertyCallbackInfo<v8::Value>& info) {
     23   v8::Isolate* isolate = info.GetIsolate();
     24   v8::Local<v8::Context> context = isolate->GetCurrentContext();
     25   if (!property->Equals(context, v8_str("cross_context_int")).FromJust())
     26     return;
     27   if (value->IsInt32()) {
     28     g_cross_context_int = value->ToInt32(context).ToLocalChecked()->Value();
     29   }
     30   info.GetReturnValue().Set(value);
     31 }
     32 
     33 void NamedQuery(v8::Local<v8::Name> property,
     34                 const v8::PropertyCallbackInfo<v8::Integer>& info) {
     35   v8::Isolate* isolate = info.GetIsolate();
     36   v8::Local<v8::Context> context = isolate->GetCurrentContext();
     37   if (!property->Equals(context, v8_str("cross_context_int")).FromJust())
     38     return;
     39   info.GetReturnValue().Set(v8::DontDelete);
     40 }
     41 
     42 void NamedDeleter(v8::Local<v8::Name> property,
     43                   const v8::PropertyCallbackInfo<v8::Boolean>& info) {
     44   v8::Isolate* isolate = info.GetIsolate();
     45   v8::Local<v8::Context> context = isolate->GetCurrentContext();
     46   if (!property->Equals(context, v8_str("cross_context_int")).FromJust())
     47     return;
     48   info.GetReturnValue().Set(false);
     49 }
     50 
     51 void NamedEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info) {
     52   v8::Isolate* isolate = info.GetIsolate();
     53   v8::Local<v8::Context> context = isolate->GetCurrentContext();
     54   v8::Local<v8::Array> names = v8::Array::New(isolate, 1);
     55   names->Set(context, 0, v8_str("cross_context_int")).FromJust();
     56   info.GetReturnValue().Set(names);
     57 }
     58 
     59 void IndexedGetter(uint32_t index,
     60                    const v8::PropertyCallbackInfo<v8::Value>& info) {
     61   if (index == 7) info.GetReturnValue().Set(g_cross_context_int);
     62 }
     63 
     64 void IndexedSetter(uint32_t index, v8::Local<v8::Value> value,
     65                    const v8::PropertyCallbackInfo<v8::Value>& info) {
     66   v8::Isolate* isolate = info.GetIsolate();
     67   v8::Local<v8::Context> context = isolate->GetCurrentContext();
     68   if (index != 7) return;
     69   if (value->IsInt32()) {
     70     g_cross_context_int = value->ToInt32(context).ToLocalChecked()->Value();
     71   }
     72   info.GetReturnValue().Set(value);
     73 }
     74 
     75 void IndexedQuery(uint32_t index,
     76                   const v8::PropertyCallbackInfo<v8::Integer>& info) {
     77   if (index == 7) info.GetReturnValue().Set(v8::DontDelete);
     78 }
     79 
     80 void IndexedDeleter(uint32_t index,
     81                     const v8::PropertyCallbackInfo<v8::Boolean>& info) {
     82   if (index == 7) info.GetReturnValue().Set(false);
     83 }
     84 
     85 void IndexedEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info) {
     86   v8::Isolate* isolate = info.GetIsolate();
     87   v8::Local<v8::Context> context = isolate->GetCurrentContext();
     88   v8::Local<v8::Array> names = v8::Array::New(isolate, 1);
     89   names->Set(context, 0, v8_str("7")).FromJust();
     90   info.GetReturnValue().Set(names);
     91 }
     92 
     93 bool AccessCheck(v8::Local<v8::Context> accessing_context,
     94                  v8::Local<v8::Object> accessed_object,
     95                  v8::Local<v8::Value> data) {
     96   return false;
     97 }
     98 
     99 void GetCrossContextInt(v8::Local<v8::String> property,
    100                         const v8::PropertyCallbackInfo<v8::Value>& info) {
    101   info.GetReturnValue().Set(g_cross_context_int);
    102 }
    103 
    104 void SetCrossContextInt(v8::Local<v8::String> property,
    105                         v8::Local<v8::Value> value,
    106                         const v8::PropertyCallbackInfo<void>& info) {
    107   v8::Isolate* isolate = info.GetIsolate();
    108   v8::Local<v8::Context> context = isolate->GetCurrentContext();
    109   if (value->IsInt32()) {
    110     g_cross_context_int = value->ToInt32(context).ToLocalChecked()->Value();
    111   }
    112 }
    113 
    114 void Return42(v8::Local<v8::String> property,
    115               const v8::PropertyCallbackInfo<v8::Value>& info) {
    116   info.GetReturnValue().Set(42);
    117 }
    118 
    119 }  // namespace
    120 
    121 TEST(AccessCheckWithInterceptor) {
    122   v8::Isolate* isolate = CcTest::isolate();
    123   v8::HandleScope scope(isolate);
    124   v8::Local<v8::ObjectTemplate> global_template =
    125       v8::ObjectTemplate::New(isolate);
    126   global_template->SetAccessCheckCallbackAndHandler(
    127       AccessCheck,
    128       v8::NamedPropertyHandlerConfiguration(
    129           NamedGetter, NamedSetter, NamedQuery, NamedDeleter, NamedEnumerator),
    130       v8::IndexedPropertyHandlerConfiguration(IndexedGetter, IndexedSetter,
    131                                               IndexedQuery, IndexedDeleter,
    132                                               IndexedEnumerator));
    133   global_template->SetNativeDataProperty(
    134       v8_str("cross_context_int"), GetCrossContextInt, SetCrossContextInt);
    135   global_template->SetNativeDataProperty(
    136       v8_str("all_can_read"), Return42, nullptr, v8::Local<v8::Value>(),
    137       v8::None, v8::Local<v8::AccessorSignature>(), v8::ALL_CAN_READ);
    138 
    139   v8::Local<v8::Context> context0 =
    140       v8::Context::New(isolate, nullptr, global_template);
    141   context0->Enter();
    142 
    143   // Running script in this context should work.
    144   CompileRunChecked(isolate, "this.foo = 42; this[23] = true;");
    145   ExpectInt32("this.all_can_read", 42);
    146   CompileRunChecked(isolate, "this.cross_context_int = 23");
    147   CHECK_EQ(g_cross_context_int, 23);
    148   ExpectInt32("this.cross_context_int", 23);
    149 
    150   // Create another context.
    151   {
    152     v8::HandleScope other_scope(isolate);
    153     v8::Local<v8::Context> context1 =
    154         v8::Context::New(isolate, nullptr, global_template);
    155     context1->Global()
    156         ->Set(context1, v8_str("other"), context0->Global())
    157         .FromJust();
    158     v8::Context::Scope context_scope(context1);
    159 
    160     {
    161       v8::TryCatch try_catch(isolate);
    162       CHECK(CompileRun(context1, "this.other.foo").IsEmpty());
    163     }
    164     {
    165       v8::TryCatch try_catch(isolate);
    166       CHECK(CompileRun(context1, "this.other[23]").IsEmpty());
    167     }
    168 
    169     // AllCanRead properties are also inaccessible.
    170     {
    171       v8::TryCatch try_catch(isolate);
    172       CHECK(CompileRun(context1, "this.other.all_can_read").IsEmpty());
    173     }
    174 
    175     // Intercepted properties are accessible, however.
    176     ExpectInt32("this.other.cross_context_int", 23);
    177     CompileRunChecked(isolate, "this.other.cross_context_int = 42");
    178     ExpectInt32("this.other[7]", 42);
    179     ExpectString("JSON.stringify(Object.getOwnPropertyNames(this.other))",
    180                  "[\"7\",\"cross_context_int\"]");
    181   }
    182 }
    183