Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(438)

Unified Diff: test/cctest/test-object-observe.cc

Issue 22962009: Add access check for observed objects (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Merged to trunk Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/runtime.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: test/cctest/test-object-observe.cc
diff --git a/test/cctest/test-object-observe.cc b/test/cctest/test-object-observe.cc
index e7cf1e5993746179ade2ad6e26caf23b61d89973..b129ff3af4ceb2e2fa4f78b0e60ce7f3765180aa 100644
--- a/test/cctest/test-object-observe.cc
+++ b/test/cctest/test-object-observe.cc
@@ -313,11 +313,13 @@ static void ExpectRecords(Handle<Value> records,
recordObj->Get(String::New("object"))));
CHECK(String::New(expectations[i].type)->Equals(
recordObj->Get(String::New("type"))));
- CHECK(String::New(expectations[i].name)->Equals(
- recordObj->Get(String::New("name"))));
- if (!expectations[i].old_value.IsEmpty()) {
- CHECK(expectations[i].old_value->Equals(
- recordObj->Get(String::New("oldValue"))));
+ if (strcmp("splice", expectations[i].type) != 0) {
+ CHECK(String::New(expectations[i].name)->Equals(
+ recordObj->Get(String::New("name"))));
+ if (!expectations[i].old_value.IsEmpty()) {
+ CHECK(expectations[i].old_value->Equals(
+ recordObj->Get(String::New("oldValue"))));
+ }
}
}
}
@@ -446,3 +448,270 @@ TEST(ObservationWeakMap) {
CHECK_EQ(0, NumberOfElements(objectInfoMap));
CHECK_EQ(0, NumberOfElements(notifierObjectInfoMap));
}
+
+
+static bool NamedAccessAlwaysAllowed(Local<Object>, Local<Value>, AccessType,
+ Local<Value>) {
+ return true;
+}
+
+
+static bool IndexedAccessAlwaysAllowed(Local<Object>, uint32_t, AccessType,
+ Local<Value>) {
+ return true;
+}
+
+
+static AccessType g_access_block_type = ACCESS_GET;
+
+
+static bool NamedAccessAllowUnlessBlocked(Local<Object> host,
+ Local<Value> key,
+ AccessType type,
+ Local<Value>) {
+ if (type != g_access_block_type) return true;
+ Handle<Object> global = Context::GetCurrent()->Global();
+ Handle<Value> blacklist = global->Get(String::New("blacklist"));
+ if (!blacklist->IsObject()) return true;
+ if (key->IsString()) return !blacklist.As<Object>()->Has(key);
+ return true;
+}
+
+
+static bool IndexedAccessAllowUnlessBlocked(Local<Object> host,
+ uint32_t index,
+ AccessType type,
+ Local<Value>) {
+ if (type != ACCESS_GET) return true;
+ Handle<Object> global = Context::GetCurrent()->Global();
+ Handle<Value> blacklist = global->Get(String::New("blacklist"));
+ if (!blacklist->IsObject()) return true;
+ return !blacklist.As<Object>()->Has(index);
+}
+
+
+static bool BlockAccessKeys(Local<Object> host, Local<Value> key,
+ AccessType type, Local<Value>) {
+ Handle<Object> global = Context::GetCurrent()->Global();
+ Handle<Value> blacklist = global->Get(String::New("blacklist"));
+ if (!blacklist->IsObject()) return true;
+ return type != ACCESS_KEYS ||
+ !blacklist.As<Object>()->Has(String::New("__block_access_keys"));
+}
+
+
+static Handle<Object> CreateAccessCheckedObject(
+ NamedSecurityCallback namedCallback,
+ IndexedSecurityCallback indexedCallback) {
+ Handle<ObjectTemplate> tmpl = ObjectTemplate::New();
+ tmpl->SetAccessCheckCallbacks(namedCallback, indexedCallback);
+ Handle<Object> instance = tmpl->NewInstance();
+ instance->CreationContext()->Global()->Set(String::New("obj"), instance);
+ return instance;
+}
+
+
+TEST(NamedAccessCheck) {
+ HarmonyIsolate isolate;
+ const AccessType types[] = { ACCESS_GET, ACCESS_HAS };
+ for (size_t i = 0; i < ARRAY_SIZE(types); ++i) {
+ HandleScope scope(isolate.GetIsolate());
+ LocalContext context;
+ g_access_block_type = types[i];
+ Handle<Object> instance = CreateAccessCheckedObject(
+ NamedAccessAllowUnlessBlocked, IndexedAccessAlwaysAllowed);
+ CompileRun("var records = null;"
+ "var objNoCheck = {};"
+ "var blacklist = {foo: true};"
+ "var observer = function(r) { records = r };"
+ "Object.observe(obj, observer);"
+ "Object.observe(objNoCheck, observer);");
+ Handle<Value> obj_no_check = CompileRun("objNoCheck");
+ {
+ LocalContext context2;
+ context2->Global()->Set(String::New("obj"), instance);
+ context2->Global()->Set(String::New("objNoCheck"), obj_no_check);
+ CompileRun("var records2 = null;"
+ "var observer2 = function(r) { records2 = r };"
+ "Object.observe(obj, observer2);"
+ "Object.observe(objNoCheck, observer2);"
+ "obj.foo = 'bar';"
+ "Object.defineProperty(obj, 'foo', {value: 5});"
+ "Object.defineProperty(obj, 'foo', {get: function(){}});"
+ "obj.bar = 'baz';"
+ "objNoCheck.baz = 'quux'");
+ const RecordExpectation expected_records2[] = {
+ { instance, "new", "foo", Handle<Value>() },
+ { instance, "updated", "foo", String::New("bar") },
+ { instance, "reconfigured", "foo", Number::New(5) },
+ { instance, "new", "bar", Handle<Value>() },
+ { obj_no_check, "new", "baz", Handle<Value>() },
+ };
+ EXPECT_RECORDS(CompileRun("records2"), expected_records2);
+ }
+ const RecordExpectation expected_records[] = {
+ { instance, "new", "bar", Handle<Value>() },
+ { obj_no_check, "new", "baz", Handle<Value>() }
+ };
+ EXPECT_RECORDS(CompileRun("records"), expected_records);
+ }
+}
+
+
+TEST(IndexedAccessCheck) {
+ HarmonyIsolate isolate;
+ const AccessType types[] = { ACCESS_GET, ACCESS_HAS };
+ for (size_t i = 0; i < ARRAY_SIZE(types); ++i) {
+ HandleScope scope(isolate.GetIsolate());
+ LocalContext context;
+ g_access_block_type = types[i];
+ Handle<Object> instance = CreateAccessCheckedObject(
+ NamedAccessAlwaysAllowed, IndexedAccessAllowUnlessBlocked);
+ CompileRun("var records = null;"
+ "var objNoCheck = {};"
+ "var blacklist = {7: true};"
+ "var observer = function(r) { records = r };"
+ "Object.observe(obj, observer);"
+ "Object.observe(objNoCheck, observer);");
+ Handle<Value> obj_no_check = CompileRun("objNoCheck");
+ {
+ LocalContext context2;
+ context2->Global()->Set(String::New("obj"), instance);
+ context2->Global()->Set(String::New("objNoCheck"), obj_no_check);
+ CompileRun("var records2 = null;"
+ "var observer2 = function(r) { records2 = r };"
+ "Object.observe(obj, observer2);"
+ "Object.observe(objNoCheck, observer2);"
+ "obj[7] = 'foo';"
+ "Object.defineProperty(obj, '7', {value: 5});"
+ "Object.defineProperty(obj, '7', {get: function(){}});"
+ "obj[8] = 'bar';"
+ "objNoCheck[42] = 'quux'");
+ const RecordExpectation expected_records2[] = {
+ { instance, "new", "7", Handle<Value>() },
+ { instance, "updated", "7", String::New("foo") },
+ { instance, "reconfigured", "7", Number::New(5) },
+ { instance, "new", "8", Handle<Value>() },
+ { obj_no_check, "new", "42", Handle<Value>() }
+ };
+ EXPECT_RECORDS(CompileRun("records2"), expected_records2);
+ }
+ const RecordExpectation expected_records[] = {
+ { instance, "new", "8", Handle<Value>() },
+ { obj_no_check, "new", "42", Handle<Value>() }
+ };
+ EXPECT_RECORDS(CompileRun("records"), expected_records);
+ }
+}
+
+
+TEST(SpliceAccessCheck) {
+ HarmonyIsolate isolate;
+ HandleScope scope(isolate.GetIsolate());
+ LocalContext context;
+ g_access_block_type = ACCESS_GET;
+ Handle<Object> instance = CreateAccessCheckedObject(
+ NamedAccessAlwaysAllowed, IndexedAccessAllowUnlessBlocked);
+ CompileRun("var records = null;"
+ "obj[1] = 'foo';"
+ "obj.length = 2;"
+ "var objNoCheck = {1: 'bar', length: 2};"
+ "var blacklist = {1: true};"
+ "observer = function(r) { records = r };"
+ "Array.observe(obj, observer);"
+ "Array.observe(objNoCheck, observer);");
+ Handle<Value> obj_no_check = CompileRun("objNoCheck");
+ {
+ LocalContext context2;
+ context2->Global()->Set(String::New("obj"), instance);
+ context2->Global()->Set(String::New("objNoCheck"), obj_no_check);
+ CompileRun("var records2 = null;"
+ "var observer2 = function(r) { records2 = r };"
+ "Array.observe(obj, observer2);"
+ "Array.observe(objNoCheck, observer2);"
+ // No one should hear about this: no splice records are emitted
+ // for access-checked objects
+ "[].push.call(obj, 5);"
+ "[].splice.call(obj, 1, 1);"
+ "[].pop.call(obj);"
+ "[].pop.call(objNoCheck);");
+ // TODO(adamk): Extend EXPECT_RECORDS to be able to assert more things
+ // about splice records. For this test it's not so important since
+ // we just want to guarantee the machinery is in operation at all.
+ const RecordExpectation expected_records2[] = {
+ { obj_no_check, "splice", "", Handle<Value>() }
+ };
+ EXPECT_RECORDS(CompileRun("records2"), expected_records2);
+ }
+ const RecordExpectation expected_records[] = {
+ { obj_no_check, "splice", "", Handle<Value>() }
+ };
+ EXPECT_RECORDS(CompileRun("records"), expected_records);
+}
+
+
+TEST(DisallowAllForAccessKeys) {
+ HarmonyIsolate isolate;
+ HandleScope scope(isolate.GetIsolate());
+ LocalContext context;
+ Handle<Object> instance = CreateAccessCheckedObject(
+ BlockAccessKeys, IndexedAccessAlwaysAllowed);
+ CompileRun("var records = null;"
+ "var objNoCheck = {};"
+ "var observer = function(r) { records = r };"
+ "var blacklist = {__block_access_keys: true};"
+ "Object.observe(obj, observer);"
+ "Object.observe(objNoCheck, observer);");
+ Handle<Value> obj_no_check = CompileRun("objNoCheck");
+ {
+ LocalContext context2;
+ context2->Global()->Set(String::New("obj"), instance);
+ context2->Global()->Set(String::New("objNoCheck"), obj_no_check);
+ CompileRun("var records2 = null;"
+ "var observer2 = function(r) { records2 = r };"
+ "Object.observe(obj, observer2);"
+ "Object.observe(objNoCheck, observer2);"
+ "obj.foo = 'bar';"
+ "obj[5] = 'baz';"
+ "objNoCheck.baz = 'quux'");
+ const RecordExpectation expected_records2[] = {
+ { instance, "new", "foo", Handle<Value>() },
+ { instance, "new", "5", Handle<Value>() },
+ { obj_no_check, "new", "baz", Handle<Value>() },
+ };
+ EXPECT_RECORDS(CompileRun("records2"), expected_records2);
+ }
+ const RecordExpectation expected_records[] = {
+ { obj_no_check, "new", "baz", Handle<Value>() }
+ };
+ EXPECT_RECORDS(CompileRun("records"), expected_records);
+}
+
+
+TEST(AccessCheckDisallowApiModifications) {
+ HarmonyIsolate isolate;
+ HandleScope scope(isolate.GetIsolate());
+ LocalContext context;
+ Handle<Object> instance = CreateAccessCheckedObject(
+ BlockAccessKeys, IndexedAccessAlwaysAllowed);
+ CompileRun("var records = null;"
+ "var observer = function(r) { records = r };"
+ "var blacklist = {__block_access_keys: true};"
+ "Object.observe(obj, observer);");
+ {
+ LocalContext context2;
+ context2->Global()->Set(String::New("obj"), instance);
+ CompileRun("var records2 = null;"
+ "var observer2 = function(r) { records2 = r };"
+ "Object.observe(obj, observer2);");
+ instance->Set(5, String::New("bar"));
+ instance->Set(String::New("foo"), String::New("bar"));
+ CompileRun(""); // trigger delivery
+ const RecordExpectation expected_records2[] = {
+ { instance, "new", "5", Handle<Value>() },
+ { instance, "new", "foo", Handle<Value>() }
+ };
+ EXPECT_RECORDS(CompileRun("records2"), expected_records2);
+ }
+ CHECK(CompileRun("records")->IsNull());
+}
« no previous file with comments | « src/runtime.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698