• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
NamedGetter(v8::Local<v8::Name> property,const v8::PropertyCallbackInfo<v8::Value> & info)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 
NamedSetter(v8::Local<v8::Name> property,v8::Local<v8::Value> value,const v8::PropertyCallbackInfo<v8::Value> & info)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 
NamedQuery(v8::Local<v8::Name> property,const v8::PropertyCallbackInfo<v8::Integer> & info)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 
NamedDeleter(v8::Local<v8::Name> property,const v8::PropertyCallbackInfo<v8::Boolean> & info)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 
NamedEnumerator(const v8::PropertyCallbackInfo<v8::Array> & info)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 
IndexedGetter(uint32_t index,const v8::PropertyCallbackInfo<v8::Value> & info)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 
IndexedSetter(uint32_t index,v8::Local<v8::Value> value,const v8::PropertyCallbackInfo<v8::Value> & info)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 
IndexedQuery(uint32_t index,const v8::PropertyCallbackInfo<v8::Integer> & info)75 void IndexedQuery(uint32_t index,
76                   const v8::PropertyCallbackInfo<v8::Integer>& info) {
77   if (index == 7) info.GetReturnValue().Set(v8::DontDelete);
78 }
79 
IndexedDeleter(uint32_t index,const v8::PropertyCallbackInfo<v8::Boolean> & info)80 void IndexedDeleter(uint32_t index,
81                     const v8::PropertyCallbackInfo<v8::Boolean>& info) {
82   if (index == 7) info.GetReturnValue().Set(false);
83 }
84 
IndexedEnumerator(const v8::PropertyCallbackInfo<v8::Array> & info)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 
AccessCheck(v8::Local<v8::Context> accessing_context,v8::Local<v8::Object> accessed_object,v8::Local<v8::Value> data)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 
GetCrossContextInt(v8::Local<v8::String> property,const v8::PropertyCallbackInfo<v8::Value> & info)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 
SetCrossContextInt(v8::Local<v8::String> property,v8::Local<v8::Value> value,const v8::PropertyCallbackInfo<void> & info)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 
Return42(v8::Local<v8::String> property,const v8::PropertyCallbackInfo<v8::Value> & info)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 
TEST(AccessCheckWithInterceptor)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