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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/runtime.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after
306 Handle<Array> recordArray = records.As<Array>(); 306 Handle<Array> recordArray = records.As<Array>();
307 CHECK_EQ(num, static_cast<int>(recordArray->Length())); 307 CHECK_EQ(num, static_cast<int>(recordArray->Length()));
308 for (int i = 0; i < num; ++i) { 308 for (int i = 0; i < num; ++i) {
309 Handle<Value> record = recordArray->Get(i); 309 Handle<Value> record = recordArray->Get(i);
310 CHECK(record->IsObject()); 310 CHECK(record->IsObject());
311 Handle<Object> recordObj = record.As<Object>(); 311 Handle<Object> recordObj = record.As<Object>();
312 CHECK(expectations[i].object->StrictEquals( 312 CHECK(expectations[i].object->StrictEquals(
313 recordObj->Get(String::New("object")))); 313 recordObj->Get(String::New("object"))));
314 CHECK(String::New(expectations[i].type)->Equals( 314 CHECK(String::New(expectations[i].type)->Equals(
315 recordObj->Get(String::New("type")))); 315 recordObj->Get(String::New("type"))));
316 CHECK(String::New(expectations[i].name)->Equals( 316 if (strcmp("splice", expectations[i].type) != 0) {
317 recordObj->Get(String::New("name")))); 317 CHECK(String::New(expectations[i].name)->Equals(
318 if (!expectations[i].old_value.IsEmpty()) { 318 recordObj->Get(String::New("name"))));
319 CHECK(expectations[i].old_value->Equals( 319 if (!expectations[i].old_value.IsEmpty()) {
320 recordObj->Get(String::New("oldValue")))); 320 CHECK(expectations[i].old_value->Equals(
321 recordObj->Get(String::New("oldValue"))));
322 }
321 } 323 }
322 } 324 }
323 } 325 }
324 326
325 #define EXPECT_RECORDS(records, expectations) \ 327 #define EXPECT_RECORDS(records, expectations) \
326 ExpectRecords(records, expectations, ARRAY_SIZE(expectations)) 328 ExpectRecords(records, expectations, ARRAY_SIZE(expectations))
327 329
328 TEST(APITestBasicMutation) { 330 TEST(APITestBasicMutation) {
329 HarmonyIsolate isolate; 331 HarmonyIsolate isolate;
330 HandleScope scope(isolate.GetIsolate()); 332 HandleScope scope(isolate.GetIsolate());
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
439 i::Handle<i::JSWeakMap>::cast( 441 i::Handle<i::JSWeakMap>::cast(
440 i::GetProperty(observation_state, "notifierObjectInfoMap")); 442 i::GetProperty(observation_state, "notifierObjectInfoMap"));
441 CHECK_EQ(1, NumberOfElements(callbackInfoMap)); 443 CHECK_EQ(1, NumberOfElements(callbackInfoMap));
442 CHECK_EQ(1, NumberOfElements(objectInfoMap)); 444 CHECK_EQ(1, NumberOfElements(objectInfoMap));
443 CHECK_EQ(1, NumberOfElements(notifierObjectInfoMap)); 445 CHECK_EQ(1, NumberOfElements(notifierObjectInfoMap));
444 HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); 446 HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
445 CHECK_EQ(0, NumberOfElements(callbackInfoMap)); 447 CHECK_EQ(0, NumberOfElements(callbackInfoMap));
446 CHECK_EQ(0, NumberOfElements(objectInfoMap)); 448 CHECK_EQ(0, NumberOfElements(objectInfoMap));
447 CHECK_EQ(0, NumberOfElements(notifierObjectInfoMap)); 449 CHECK_EQ(0, NumberOfElements(notifierObjectInfoMap));
448 } 450 }
451
452
453 static bool NamedAccessAlwaysAllowed(Local<Object>, Local<Value>, AccessType,
454 Local<Value>) {
455 return true;
456 }
457
458
459 static bool IndexedAccessAlwaysAllowed(Local<Object>, uint32_t, AccessType,
460 Local<Value>) {
461 return true;
462 }
463
464
465 static AccessType g_access_block_type = ACCESS_GET;
466
467
468 static bool NamedAccessAllowUnlessBlocked(Local<Object> host,
469 Local<Value> key,
470 AccessType type,
471 Local<Value>) {
472 if (type != g_access_block_type) return true;
473 Handle<Object> global = Context::GetCurrent()->Global();
474 Handle<Value> blacklist = global->Get(String::New("blacklist"));
475 if (!blacklist->IsObject()) return true;
476 if (key->IsString()) return !blacklist.As<Object>()->Has(key);
477 return true;
478 }
479
480
481 static bool IndexedAccessAllowUnlessBlocked(Local<Object> host,
482 uint32_t index,
483 AccessType type,
484 Local<Value>) {
485 if (type != ACCESS_GET) return true;
486 Handle<Object> global = Context::GetCurrent()->Global();
487 Handle<Value> blacklist = global->Get(String::New("blacklist"));
488 if (!blacklist->IsObject()) return true;
489 return !blacklist.As<Object>()->Has(index);
490 }
491
492
493 static bool BlockAccessKeys(Local<Object> host, Local<Value> key,
494 AccessType type, Local<Value>) {
495 Handle<Object> global = Context::GetCurrent()->Global();
496 Handle<Value> blacklist = global->Get(String::New("blacklist"));
497 if (!blacklist->IsObject()) return true;
498 return type != ACCESS_KEYS ||
499 !blacklist.As<Object>()->Has(String::New("__block_access_keys"));
500 }
501
502
503 static Handle<Object> CreateAccessCheckedObject(
504 NamedSecurityCallback namedCallback,
505 IndexedSecurityCallback indexedCallback) {
506 Handle<ObjectTemplate> tmpl = ObjectTemplate::New();
507 tmpl->SetAccessCheckCallbacks(namedCallback, indexedCallback);
508 Handle<Object> instance = tmpl->NewInstance();
509 instance->CreationContext()->Global()->Set(String::New("obj"), instance);
510 return instance;
511 }
512
513
514 TEST(NamedAccessCheck) {
515 HarmonyIsolate isolate;
516 const AccessType types[] = { ACCESS_GET, ACCESS_HAS };
517 for (size_t i = 0; i < ARRAY_SIZE(types); ++i) {
518 HandleScope scope(isolate.GetIsolate());
519 LocalContext context;
520 g_access_block_type = types[i];
521 Handle<Object> instance = CreateAccessCheckedObject(
522 NamedAccessAllowUnlessBlocked, IndexedAccessAlwaysAllowed);
523 CompileRun("var records = null;"
524 "var objNoCheck = {};"
525 "var blacklist = {foo: true};"
526 "var observer = function(r) { records = r };"
527 "Object.observe(obj, observer);"
528 "Object.observe(objNoCheck, observer);");
529 Handle<Value> obj_no_check = CompileRun("objNoCheck");
530 {
531 LocalContext context2;
532 context2->Global()->Set(String::New("obj"), instance);
533 context2->Global()->Set(String::New("objNoCheck"), obj_no_check);
534 CompileRun("var records2 = null;"
535 "var observer2 = function(r) { records2 = r };"
536 "Object.observe(obj, observer2);"
537 "Object.observe(objNoCheck, observer2);"
538 "obj.foo = 'bar';"
539 "Object.defineProperty(obj, 'foo', {value: 5});"
540 "Object.defineProperty(obj, 'foo', {get: function(){}});"
541 "obj.bar = 'baz';"
542 "objNoCheck.baz = 'quux'");
543 const RecordExpectation expected_records2[] = {
544 { instance, "new", "foo", Handle<Value>() },
545 { instance, "updated", "foo", String::New("bar") },
546 { instance, "reconfigured", "foo", Number::New(5) },
547 { instance, "new", "bar", Handle<Value>() },
548 { obj_no_check, "new", "baz", Handle<Value>() },
549 };
550 EXPECT_RECORDS(CompileRun("records2"), expected_records2);
551 }
552 const RecordExpectation expected_records[] = {
553 { instance, "new", "bar", Handle<Value>() },
554 { obj_no_check, "new", "baz", Handle<Value>() }
555 };
556 EXPECT_RECORDS(CompileRun("records"), expected_records);
557 }
558 }
559
560
561 TEST(IndexedAccessCheck) {
562 HarmonyIsolate isolate;
563 const AccessType types[] = { ACCESS_GET, ACCESS_HAS };
564 for (size_t i = 0; i < ARRAY_SIZE(types); ++i) {
565 HandleScope scope(isolate.GetIsolate());
566 LocalContext context;
567 g_access_block_type = types[i];
568 Handle<Object> instance = CreateAccessCheckedObject(
569 NamedAccessAlwaysAllowed, IndexedAccessAllowUnlessBlocked);
570 CompileRun("var records = null;"
571 "var objNoCheck = {};"
572 "var blacklist = {7: true};"
573 "var observer = function(r) { records = r };"
574 "Object.observe(obj, observer);"
575 "Object.observe(objNoCheck, observer);");
576 Handle<Value> obj_no_check = CompileRun("objNoCheck");
577 {
578 LocalContext context2;
579 context2->Global()->Set(String::New("obj"), instance);
580 context2->Global()->Set(String::New("objNoCheck"), obj_no_check);
581 CompileRun("var records2 = null;"
582 "var observer2 = function(r) { records2 = r };"
583 "Object.observe(obj, observer2);"
584 "Object.observe(objNoCheck, observer2);"
585 "obj[7] = 'foo';"
586 "Object.defineProperty(obj, '7', {value: 5});"
587 "Object.defineProperty(obj, '7', {get: function(){}});"
588 "obj[8] = 'bar';"
589 "objNoCheck[42] = 'quux'");
590 const RecordExpectation expected_records2[] = {
591 { instance, "new", "7", Handle<Value>() },
592 { instance, "updated", "7", String::New("foo") },
593 { instance, "reconfigured", "7", Number::New(5) },
594 { instance, "new", "8", Handle<Value>() },
595 { obj_no_check, "new", "42", Handle<Value>() }
596 };
597 EXPECT_RECORDS(CompileRun("records2"), expected_records2);
598 }
599 const RecordExpectation expected_records[] = {
600 { instance, "new", "8", Handle<Value>() },
601 { obj_no_check, "new", "42", Handle<Value>() }
602 };
603 EXPECT_RECORDS(CompileRun("records"), expected_records);
604 }
605 }
606
607
608 TEST(SpliceAccessCheck) {
609 HarmonyIsolate isolate;
610 HandleScope scope(isolate.GetIsolate());
611 LocalContext context;
612 g_access_block_type = ACCESS_GET;
613 Handle<Object> instance = CreateAccessCheckedObject(
614 NamedAccessAlwaysAllowed, IndexedAccessAllowUnlessBlocked);
615 CompileRun("var records = null;"
616 "obj[1] = 'foo';"
617 "obj.length = 2;"
618 "var objNoCheck = {1: 'bar', length: 2};"
619 "var blacklist = {1: true};"
620 "observer = function(r) { records = r };"
621 "Array.observe(obj, observer);"
622 "Array.observe(objNoCheck, observer);");
623 Handle<Value> obj_no_check = CompileRun("objNoCheck");
624 {
625 LocalContext context2;
626 context2->Global()->Set(String::New("obj"), instance);
627 context2->Global()->Set(String::New("objNoCheck"), obj_no_check);
628 CompileRun("var records2 = null;"
629 "var observer2 = function(r) { records2 = r };"
630 "Array.observe(obj, observer2);"
631 "Array.observe(objNoCheck, observer2);"
632 // No one should hear about this: no splice records are emitted
633 // for access-checked objects
634 "[].push.call(obj, 5);"
635 "[].splice.call(obj, 1, 1);"
636 "[].pop.call(obj);"
637 "[].pop.call(objNoCheck);");
638 // TODO(adamk): Extend EXPECT_RECORDS to be able to assert more things
639 // about splice records. For this test it's not so important since
640 // we just want to guarantee the machinery is in operation at all.
641 const RecordExpectation expected_records2[] = {
642 { obj_no_check, "splice", "", Handle<Value>() }
643 };
644 EXPECT_RECORDS(CompileRun("records2"), expected_records2);
645 }
646 const RecordExpectation expected_records[] = {
647 { obj_no_check, "splice", "", Handle<Value>() }
648 };
649 EXPECT_RECORDS(CompileRun("records"), expected_records);
650 }
651
652
653 TEST(DisallowAllForAccessKeys) {
654 HarmonyIsolate isolate;
655 HandleScope scope(isolate.GetIsolate());
656 LocalContext context;
657 Handle<Object> instance = CreateAccessCheckedObject(
658 BlockAccessKeys, IndexedAccessAlwaysAllowed);
659 CompileRun("var records = null;"
660 "var objNoCheck = {};"
661 "var observer = function(r) { records = r };"
662 "var blacklist = {__block_access_keys: true};"
663 "Object.observe(obj, observer);"
664 "Object.observe(objNoCheck, observer);");
665 Handle<Value> obj_no_check = CompileRun("objNoCheck");
666 {
667 LocalContext context2;
668 context2->Global()->Set(String::New("obj"), instance);
669 context2->Global()->Set(String::New("objNoCheck"), obj_no_check);
670 CompileRun("var records2 = null;"
671 "var observer2 = function(r) { records2 = r };"
672 "Object.observe(obj, observer2);"
673 "Object.observe(objNoCheck, observer2);"
674 "obj.foo = 'bar';"
675 "obj[5] = 'baz';"
676 "objNoCheck.baz = 'quux'");
677 const RecordExpectation expected_records2[] = {
678 { instance, "new", "foo", Handle<Value>() },
679 { instance, "new", "5", Handle<Value>() },
680 { obj_no_check, "new", "baz", Handle<Value>() },
681 };
682 EXPECT_RECORDS(CompileRun("records2"), expected_records2);
683 }
684 const RecordExpectation expected_records[] = {
685 { obj_no_check, "new", "baz", Handle<Value>() }
686 };
687 EXPECT_RECORDS(CompileRun("records"), expected_records);
688 }
689
690
691 TEST(AccessCheckDisallowApiModifications) {
692 HarmonyIsolate isolate;
693 HandleScope scope(isolate.GetIsolate());
694 LocalContext context;
695 Handle<Object> instance = CreateAccessCheckedObject(
696 BlockAccessKeys, IndexedAccessAlwaysAllowed);
697 CompileRun("var records = null;"
698 "var observer = function(r) { records = r };"
699 "var blacklist = {__block_access_keys: true};"
700 "Object.observe(obj, observer);");
701 {
702 LocalContext context2;
703 context2->Global()->Set(String::New("obj"), instance);
704 CompileRun("var records2 = null;"
705 "var observer2 = function(r) { records2 = r };"
706 "Object.observe(obj, observer2);");
707 instance->Set(5, String::New("bar"));
708 instance->Set(String::New("foo"), String::New("bar"));
709 CompileRun(""); // trigger delivery
710 const RecordExpectation expected_records2[] = {
711 { instance, "new", "5", Handle<Value>() },
712 { instance, "new", "foo", Handle<Value>() }
713 };
714 EXPECT_RECORDS(CompileRun("records2"), expected_records2);
715 }
716 CHECK(CompileRun("records")->IsNull());
717 }
OLDNEW
« 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