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

Side by Side Diff: test/cctest/test-object-observe.cc

Issue 265503002: Re-enable Object.observe and add enforcement for security invariants. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: cleanup Created 6 years, 7 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
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 424 matching lines...) Expand 10 before | Expand all | Expand 10 after
435 return true; 435 return true;
436 } 436 }
437 437
438 438
439 static bool IndexedAccessAlwaysAllowed(Local<Object>, uint32_t, AccessType, 439 static bool IndexedAccessAlwaysAllowed(Local<Object>, uint32_t, AccessType,
440 Local<Value>) { 440 Local<Value>) {
441 return true; 441 return true;
442 } 442 }
443 443
444 444
445 static AccessType g_access_block_type = ACCESS_GET; 445 static int TestObserveSecurity(Handle<Context> observer_context,
446 Handle<Context> object_context,
447 Handle<Context> mutation_context,
448 bool use_access_checked_object = true) {
449 Context::Scope observer_scope(observer_context);
450 CompileRun("var records = null;"
451 "var observer = function(r) { records = r };");
452 Handle<Value> observer = CompileRun("observer");
453 {
454 Context::Scope object_scope(object_context);
455 object_context->Global()->Set(
456 String::NewFromUtf8(CcTest::isolate(), "observer"), observer);
457
458 Handle<ObjectTemplate> tmpl = ObjectTemplate::New(CcTest::isolate());
459 if (use_access_checked_object) {
460 tmpl->SetAccessCheckCallbacks(NamedAccessAlwaysAllowed,
461 IndexedAccessAlwaysAllowed);
462 }
463 Handle<Object> obj = tmpl->NewInstance();
464 object_context->Global()->Set(
465 String::NewFromUtf8(CcTest::isolate(), "obj"), obj);
466
467 CompileRun("obj.length = 0;"
468 "Object.observe(obj, observer,"
469 "['add', 'update', 'delete','reconfigure','splice']"
470 ");");
471 {
472 Context::Scope mutation_scope(mutation_context);
473 mutation_context->Global()->Set(
474 String::NewFromUtf8(CcTest::isolate(), "obj"), obj);
475 CompileRun("obj.foo = 'bar';"
476 "obj.foo = 'baz';"
477 "delete obj.foo;"
478 "Object.defineProperty(obj, 'bar', {value: 'bot'});"
479 "Array.prototype.push.call(obj, 1, 2, 3);"
480 "Array.prototype.splice.call(obj, 1, 2, 2, 4);"
481 "Array.prototype.pop.call(obj);"
482 "Array.prototype.shift.call(obj);");
483 }
484 }
485 return CompileRun("records ? records.length : 0")->Int32Value();
486 }
487
488
489 TEST(ObserverSecurityAAA) {
rossberg 2014/04/30 11:28:32 How about merging all these tests into a single on
490 v8::Isolate* isolate = CcTest::isolate();
491 v8::HandleScope scope(isolate);
492 v8::Local<Context> contextA = Context::New(isolate);
493 CHECK_EQ(8, TestObserveSecurity(contextA, contextA, contextA));
494 }
495
496
497 TEST(ObserverSecurityA1A2A3) {
498 v8::Isolate* isolate = CcTest::isolate();
499 v8::HandleScope scope(isolate);
500
501 v8::Local<Context> contextA1 = Context::New(isolate);
502 v8::Local<Context> contextA2 = Context::New(isolate);
503 v8::Local<Context> contextA3 = Context::New(isolate);
504
505 Local<Value> foo = v8_str("foo");
506 contextA1->SetSecurityToken(foo);
507 contextA2->SetSecurityToken(foo);
508 contextA3->SetSecurityToken(foo);
509
510 CHECK_EQ(8, TestObserveSecurity(contextA1, contextA2, contextA3));
511 }
512
513
514 TEST(ObserverSecurityAAB) {
515 v8::Isolate* isolate = CcTest::isolate();
516 v8::HandleScope scope(isolate);
517 v8::Local<Context> contextA = Context::New(isolate);
518 v8::Local<Context> contextB = Context::New(isolate);
519 CHECK_EQ(0, TestObserveSecurity(contextA, contextA, contextB));
520 }
521
522
523 TEST(ObserverSecurityA1A2B) {
524 v8::Isolate* isolate = CcTest::isolate();
525 v8::HandleScope scope(isolate);
526
527 v8::Local<Context> contextA1 = Context::New(isolate);
528 v8::Local<Context> contextA2 = Context::New(isolate);
529 v8::Local<Context> contextB = Context::New(isolate);
530
531 Local<Value> foo = v8_str("foo");
532 contextA1->SetSecurityToken(foo);
533 contextA2->SetSecurityToken(foo);
534
535 CHECK_EQ(0, TestObserveSecurity(contextA1, contextA2, contextB));
536 }
537
538
539 TEST(ObserverSecurityABA) {
540 v8::Isolate* isolate = CcTest::isolate();
541 v8::HandleScope scope(isolate);
542 v8::Local<Context> contextA = Context::New(isolate);
543 v8::Local<Context> contextB = Context::New(isolate);
544 CHECK_EQ(0, TestObserveSecurity(contextA, contextB, contextA));
545 }
546
547
548 TEST(ObserverSecurityA1BA2) {
549 v8::Isolate* isolate = CcTest::isolate();
550 v8::HandleScope scope(isolate);
551 v8::Local<Context> contextA1 = Context::New(isolate);
552 v8::Local<Context> contextA2 = Context::New(isolate);
553 v8::Local<Context> contextB = Context::New(isolate);
554
555 Local<Value> foo = v8_str("foo");
556 contextA1->SetSecurityToken(foo);
557 contextA2->SetSecurityToken(foo);
558
559 CHECK_EQ(0, TestObserveSecurity(contextA1, contextB, contextA2));
560 }
561
562
563 TEST(ObserverSecurityBA1A2) {
564 v8::Isolate* isolate = CcTest::isolate();
565 v8::HandleScope scope(isolate);
566 v8::Local<Context> contextA1 = Context::New(isolate);
567 v8::Local<Context> contextA2 = Context::New(isolate);
568 v8::Local<Context> contextB = Context::New(isolate);
569
570 Local<Value> foo = v8_str("foo");
571 contextA1->SetSecurityToken(foo);
572 contextA2->SetSecurityToken(foo);
573
574 CHECK_EQ(0, TestObserveSecurity(contextB, contextA1, contextA2));
575 }
576
577
578 TEST(ObserverSecurityABB) {
579 v8::Isolate* isolate = CcTest::isolate();
580 v8::HandleScope scope(isolate);
581 v8::Local<Context> contextA = Context::New(isolate);
582 v8::Local<Context> contextB = Context::New(isolate);
583 CHECK_EQ(0, TestObserveSecurity(contextA, contextB, contextB));
584 }
585
586
587 TEST(ObserverSecurityAB1B2) {
rossberg 2014/04/30 11:28:32 How is this one different from BA1A2 above?
rafaelw 2014/05/02 03:22:32 yes. removed. On 2014/04/30 11:28:32, rossberg wr
588 v8::Isolate* isolate = CcTest::isolate();
589 v8::HandleScope scope(isolate);
590 v8::Local<Context> contextA = Context::New(isolate);
591 v8::Local<Context> contextB1 = Context::New(isolate);
592 v8::Local<Context> contextB2 = Context::New(isolate);
593
594 Local<Value> foo = v8_str("foo");
595 contextB1->SetSecurityToken(foo);
596 contextB2->SetSecurityToken(foo);
597
598 CHECK_EQ(0, TestObserveSecurity(contextA, contextB1, contextB2));
599 }
600
601
602 TEST(ObserverSecurityB1B2A) {
rossberg 2014/04/30 11:28:32 And this seems to be the same as A1A2B.
rafaelw 2014/05/02 03:22:32 yes. removed. On 2014/04/30 11:28:32, rossberg wr
603 v8::Isolate* isolate = CcTest::isolate();
604 v8::HandleScope scope(isolate);
605 v8::Local<Context> contextA = Context::New(isolate);
606 v8::Local<Context> contextB1 = Context::New(isolate);
607 v8::Local<Context> contextB2 = Context::New(isolate);
608
609 Local<Value> foo = v8_str("foo");
610 contextB1->SetSecurityToken(foo);
611 contextB2->SetSecurityToken(foo);
612
613 CHECK_EQ(0, TestObserveSecurity(contextB1, contextB2, contextA));
614 }
615
616
617 TEST(ObserverSecurityBAB) {
rossberg 2014/04/30 11:28:32 Same as ABA?
rafaelw 2014/05/02 03:22:32 yes. removed. On 2014/04/30 11:28:32, rossberg wr
618 v8::Isolate* isolate = CcTest::isolate();
619 v8::HandleScope scope(isolate);
620 v8::Local<Context> contextA = Context::New(isolate);
621 v8::Local<Context> contextB = Context::New(isolate);
622 CHECK_EQ(0, TestObserveSecurity(contextB, contextA, contextB));
623 }
624
625
626 TEST(ObserverSecurityB1AB2) {
rossberg 2014/04/30 11:28:32 Same as A1BA2?
rafaelw 2014/05/02 03:22:32 yes. removed. On 2014/04/30 11:28:32, rossberg wr
627 v8::Isolate* isolate = CcTest::isolate();
628 v8::HandleScope scope(isolate);
629 v8::Local<Context> contextA = Context::New(isolate);
630 v8::Local<Context> contextB1 = Context::New(isolate);
631 v8::Local<Context> contextB2 = Context::New(isolate);
632
633 Local<Value> foo = v8_str("foo");
634 contextB1->SetSecurityToken(foo);
635 contextB2->SetSecurityToken(foo);
636
637 CHECK_EQ(0, TestObserveSecurity(contextB1, contextA, contextB2));
638 }
639
640
641 TEST(ObserverSecurityNoAccessCheckOnObject) {
642 v8::Isolate* isolate = CcTest::isolate();
643 v8::HandleScope scope(isolate);
644 v8::Local<Context> contextA = Context::New(isolate);
645 v8::Local<Context> contextB = Context::New(isolate);
646 v8::Local<Context> contextC = Context::New(isolate);
647 CHECK_EQ(8, TestObserveSecurity(contextA, contextB, contextC, false));
648 }
649
650
651 TEST(ObserverSecurityNotify) {
652 v8::Isolate* isolate = CcTest::isolate();
653 v8::HandleScope scope(isolate);
654 v8::Local<Context> contextA = Context::New(isolate);
655 v8::Local<Context> contextB = Context::New(isolate);
656
657 Context::Scope scopeA(contextA);
658 Handle<ObjectTemplate> tmpl = ObjectTemplate::New(CcTest::isolate());
659 tmpl->SetAccessCheckCallbacks(NamedAccessAlwaysAllowed,
660 IndexedAccessAlwaysAllowed);
661 Handle<Object> obj = tmpl->NewInstance();
662 contextA->Global()->Set(String::NewFromUtf8(CcTest::isolate(), "obj"), obj);
663
664 CompileRun("var recordsA = null;"
665 "var observerA = function(r) { recordsA = r };"
666 "Object.observe(obj, observerA);");
667
668 {
669 Context::Scope scopeB(contextB);
670 contextB->Global()->Set(String::NewFromUtf8(CcTest::isolate(), "obj"), obj);
671 CompileRun("var recordsB = null;"
672 "var observerB = function(r) { recordsB = r };"
673 "Object.observe(obj, observerB);");
674 }
675
676 CompileRun("var notifier = Object.getNotifier(obj);"
677 "notifier.notify({ type: 'update' });");
678 CHECK_EQ(1, CompileRun("recordsA ? recordsA.length : 0")->Int32Value());
679
680 {
681 Context::Scope scopeB(contextB);
682 CHECK_EQ(0, CompileRun("recordsB ? recordsB.length : 0")->Int32Value());
683 }
684 }
685
686
687 TEST(HiddenPropertiesLeakage) {
688 HandleScope scope(CcTest::isolate());
689 LocalContext context(CcTest::isolate());
690 CompileRun("var obj = {};"
691 "var records = null;"
692 "var observer = function(r) { records = r };"
693 "Object.observe(obj, observer);");
694 Handle<Value> obj =
695 context->Global()->Get(String::NewFromUtf8(CcTest::isolate(), "obj"));
696 Handle<Object>::Cast(obj)
697 ->SetHiddenValue(String::NewFromUtf8(CcTest::isolate(), "foo"),
698 Null(CcTest::isolate()));
699 CompileRun(""); // trigger delivery
700 CHECK(CompileRun("records")->IsNull());
701 }
702
703
446 static const uint32_t kBlockedContextIndex = 1337; 704 static const uint32_t kBlockedContextIndex = 1337;
447 705
448 706
449 static bool NamedAccessAllowUnlessBlocked(Local<Object> host,
450 Local<Value> key,
451 AccessType type,
452 Local<Value> data) {
453 if (type != g_access_block_type) return true;
454 v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(
455 Utils::OpenHandle(*host)->GetIsolate());
456 Handle<Object> global = isolate->GetCurrentContext()->Global();
457 if (!global->Has(kBlockedContextIndex)) return true;
458 return !key->IsString() || !key->Equals(data);
459 }
460
461
462 static bool IndexedAccessAllowUnlessBlocked(Local<Object> host,
463 uint32_t index,
464 AccessType type,
465 Local<Value> data) {
466 if (type != g_access_block_type) return true;
467 v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(
468 Utils::OpenHandle(*host)->GetIsolate());
469 Handle<Object> global = isolate->GetCurrentContext()->Global();
470 if (!global->Has(kBlockedContextIndex)) return true;
471 return index != data->Uint32Value();
472 }
473
474
475 static bool BlockAccessKeys(Local<Object> host, Local<Value> key, 707 static bool BlockAccessKeys(Local<Object> host, Local<Value> key,
476 AccessType type, Local<Value>) { 708 AccessType type, Local<Value>) {
477 v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>( 709 v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(
478 Utils::OpenHandle(*host)->GetIsolate()); 710 Utils::OpenHandle(*host)->GetIsolate());
479 Handle<Object> global = isolate->GetCurrentContext()->Global(); 711 Handle<Object> global = isolate->GetCurrentContext()->Global();
480 return type != ACCESS_KEYS || !global->Has(kBlockedContextIndex); 712 return type != ACCESS_KEYS || !global->Has(kBlockedContextIndex);
481 } 713 }
482 714
483 715
484 static Handle<Object> CreateAccessCheckedObject( 716 static Handle<Object> CreateAccessCheckedObject(
485 v8::Isolate* isolate, 717 v8::Isolate* isolate,
486 NamedSecurityCallback namedCallback, 718 NamedSecurityCallback namedCallback,
487 IndexedSecurityCallback indexedCallback, 719 IndexedSecurityCallback indexedCallback,
488 Handle<Value> data = Handle<Value>()) { 720 Handle<Value> data = Handle<Value>()) {
489 Handle<ObjectTemplate> tmpl = ObjectTemplate::New(isolate); 721 Handle<ObjectTemplate> tmpl = ObjectTemplate::New(isolate);
490 tmpl->SetAccessCheckCallbacks(namedCallback, indexedCallback, data); 722 tmpl->SetAccessCheckCallbacks(namedCallback, indexedCallback, data);
491 Handle<Object> instance = tmpl->NewInstance(); 723 Handle<Object> instance = tmpl->NewInstance();
492 Handle<Object> global = instance->CreationContext()->Global(); 724 Handle<Object> global = instance->CreationContext()->Global();
493 global->Set(String::NewFromUtf8(isolate, "obj"), instance); 725 global->Set(String::NewFromUtf8(isolate, "obj"), instance);
494 global->Set(kBlockedContextIndex, v8::True(isolate)); 726 global->Set(kBlockedContextIndex, v8::True(isolate));
495 return instance; 727 return instance;
496 } 728 }
497 729
498 730
499 TEST(NamedAccessCheck) { 731 TEST(GetNotifierFromOtherContext) {
500 const AccessType types[] = { ACCESS_GET, ACCESS_HAS }; 732 HandleScope scope(CcTest::isolate());
501 for (size_t i = 0; i < ARRAY_SIZE(types); ++i) { 733 LocalContext context(CcTest::isolate());
502 HandleScope scope(CcTest::isolate()); 734 Handle<Object> instance = CreateAccessCheckedObject(
503 LocalContext context(CcTest::isolate()); 735 CcTest::isolate(), BlockAccessKeys, IndexedAccessAlwaysAllowed);
504 g_access_block_type = types[i]; 736 {
505 Handle<Object> instance = CreateAccessCheckedObject( 737 LocalContext context2(CcTest::isolate());
506 CcTest::isolate(), 738 context2->Global()->Set(String::NewFromUtf8(CcTest::isolate(), "obj"),
507 NamedAccessAllowUnlessBlocked, 739 instance);
508 IndexedAccessAlwaysAllowed, 740 CHECK(CompileRun("Object.getNotifier(obj)")->IsNull());
509 String::NewFromUtf8(CcTest::isolate(), "foo"));
510 CompileRun("var records = null;"
511 "var objNoCheck = {};"
512 "var observer = function(r) { records = r };"
513 "Object.observe(obj, observer);"
514 "Object.observe(objNoCheck, observer);");
515 Handle<Value> obj_no_check = CompileRun("objNoCheck");
516 {
517 LocalContext context2(CcTest::isolate());
518 context2->Global()->Set(String::NewFromUtf8(CcTest::isolate(), "obj"),
519 instance);
520 context2->Global()->Set(
521 String::NewFromUtf8(CcTest::isolate(), "objNoCheck"),
522 obj_no_check);
523 CompileRun("var records2 = null;"
524 "var observer2 = function(r) { records2 = r };"
525 "Object.observe(obj, observer2);"
526 "Object.observe(objNoCheck, observer2);"
527 "obj.foo = 'bar';"
528 "Object.defineProperty(obj, 'foo', {value: 5});"
529 "Object.defineProperty(obj, 'foo', {get: function(){}});"
530 "obj.bar = 'baz';"
531 "objNoCheck.baz = 'quux'");
532 const RecordExpectation expected_records2[] = {
533 { instance, "add", "foo", Handle<Value>() },
534 { instance, "update", "foo",
535 String::NewFromUtf8(CcTest::isolate(), "bar") },
536 { instance, "reconfigure", "foo",
537 Number::New(CcTest::isolate(), 5) },
538 { instance, "add", "bar", Handle<Value>() },
539 { obj_no_check, "add", "baz", Handle<Value>() },
540 };
541 EXPECT_RECORDS(CompileRun("records2"), expected_records2);
542 }
543 const RecordExpectation expected_records[] = {
544 { instance, "add", "bar", Handle<Value>() },
545 { obj_no_check, "add", "baz", Handle<Value>() }
546 };
547 EXPECT_RECORDS(CompileRun("records"), expected_records);
548 } 741 }
549 } 742 }
550 743
551 744
552 TEST(IndexedAccessCheck) { 745 TEST(GetNotifierFromOtherOrigin) {
553 const AccessType types[] = { ACCESS_GET, ACCESS_HAS }; 746 HandleScope scope(CcTest::isolate());
554 for (size_t i = 0; i < ARRAY_SIZE(types); ++i) { 747 Handle<Value> foo = String::NewFromUtf8(CcTest::isolate(), "foo");
555 HandleScope scope(CcTest::isolate()); 748 Handle<Value> bar = String::NewFromUtf8(CcTest::isolate(), "bar");
556 LocalContext context(CcTest::isolate()); 749 LocalContext context(CcTest::isolate());
557 g_access_block_type = types[i]; 750 context->SetSecurityToken(foo);
558 Handle<Object> instance = CreateAccessCheckedObject( 751 Handle<Object> instance = CreateAccessCheckedObject(
559 CcTest::isolate(), NamedAccessAlwaysAllowed, 752 CcTest::isolate(), BlockAccessKeys, IndexedAccessAlwaysAllowed);
560 IndexedAccessAllowUnlessBlocked, Number::New(CcTest::isolate(), 7)); 753
561 CompileRun("var records = null;" 754 {
562 "var objNoCheck = {};" 755 LocalContext context2(CcTest::isolate());
563 "var observer = function(r) { records = r };" 756 context2->SetSecurityToken(bar);
564 "Object.observe(obj, observer);" 757 context2->Global()->Set(String::NewFromUtf8(CcTest::isolate(), "obj"),
565 "Object.observe(objNoCheck, observer);"); 758 instance);
566 Handle<Value> obj_no_check = CompileRun("objNoCheck"); 759 CHECK(CompileRun("Object.getNotifier(obj)")->IsNull());
567 {
568 LocalContext context2(CcTest::isolate());
569 context2->Global()->Set(String::NewFromUtf8(CcTest::isolate(), "obj"),
570 instance);
571 context2->Global()->Set(
572 String::NewFromUtf8(CcTest::isolate(), "objNoCheck"),
573 obj_no_check);
574 CompileRun("var records2 = null;"
575 "var observer2 = function(r) { records2 = r };"
576 "Object.observe(obj, observer2);"
577 "Object.observe(objNoCheck, observer2);"
578 "obj[7] = 'foo';"
579 "Object.defineProperty(obj, '7', {value: 5});"
580 "Object.defineProperty(obj, '7', {get: function(){}});"
581 "obj[8] = 'bar';"
582 "objNoCheck[42] = 'quux'");
583 const RecordExpectation expected_records2[] = {
584 { instance, "add", "7", Handle<Value>() },
585 { instance, "update", "7",
586 String::NewFromUtf8(CcTest::isolate(), "foo") },
587 { instance, "reconfigure", "7", Number::New(CcTest::isolate(), 5) },
588 { instance, "add", "8", Handle<Value>() },
589 { obj_no_check, "add", "42", Handle<Value>() }
590 };
591 EXPECT_RECORDS(CompileRun("records2"), expected_records2);
592 }
593 const RecordExpectation expected_records[] = {
594 { instance, "add", "8", Handle<Value>() },
595 { obj_no_check, "add", "42", Handle<Value>() }
596 };
597 EXPECT_RECORDS(CompileRun("records"), expected_records);
598 } 760 }
599 } 761 }
600 762
601 763
602 TEST(SpliceAccessCheck) { 764 TEST(GetNotifierFromSameOrigin) {
765 HandleScope scope(CcTest::isolate());
766 Handle<Value> foo = String::NewFromUtf8(CcTest::isolate(), "foo");
767 LocalContext context(CcTest::isolate());
768 context->SetSecurityToken(foo);
769 Handle<Object> instance = CreateAccessCheckedObject(
770 CcTest::isolate(), BlockAccessKeys, IndexedAccessAlwaysAllowed);
771
772 {
773 LocalContext context2(CcTest::isolate());
774 context2->SetSecurityToken(foo);
775 context2->Global()->Set(String::NewFromUtf8(CcTest::isolate(), "obj"),
776 instance);
777 CHECK(CompileRun("Object.getNotifier(obj)")->IsObject());
778 }
779 }
780
781
782 // This case should never happen in a well-behaved embedder, but there's
783 // no way for V8 to prevent and API user from doing it.
rossberg 2014/04/30 11:28:32 Typo: s/and/an/
rafaelw 2014/05/02 03:22:32 Test & comment removed. On 2014/04/30 11:28:32,
784 TEST(GetNotifierFromOtherContextWithoutAccessChecks) {
603 HandleScope scope(CcTest::isolate()); 785 HandleScope scope(CcTest::isolate());
604 LocalContext context(CcTest::isolate()); 786 LocalContext context(CcTest::isolate());
605 g_access_block_type = ACCESS_GET; 787 Handle<Object> instance = Object::New(CcTest::isolate());
606 Handle<Object> instance = CreateAccessCheckedObject(
607 CcTest::isolate(), NamedAccessAlwaysAllowed,
608 IndexedAccessAllowUnlessBlocked, Number::New(CcTest::isolate(), 1));
609 CompileRun("var records = null;"
610 "obj[1] = 'foo';"
611 "obj.length = 2;"
612 "var objNoCheck = {1: 'bar', length: 2};"
613 "observer = function(r) { records = r };"
614 "Array.observe(obj, observer);"
615 "Array.observe(objNoCheck, observer);");
616 Handle<Value> obj_no_check = CompileRun("objNoCheck");
617 { 788 {
618 LocalContext context2(CcTest::isolate()); 789 LocalContext context2(CcTest::isolate());
619 context2->Global()->Set(String::NewFromUtf8(CcTest::isolate(), "obj"), 790 context2->Global()->Set(String::NewFromUtf8(CcTest::isolate(), "obj"),
620 instance); 791 instance);
621 context2->Global()->Set( 792 CHECK(CompileRun("Object.getNotifier(obj)")->IsObject());
622 String::NewFromUtf8(CcTest::isolate(), "objNoCheck"), obj_no_check);
623 CompileRun("var records2 = null;"
624 "var observer2 = function(r) { records2 = r };"
625 "Array.observe(obj, observer2);"
626 "Array.observe(objNoCheck, observer2);"
627 // No one should hear about this: no splice records are emitted
628 // for access-checked objects
629 "[].push.call(obj, 5);"
630 "[].splice.call(obj, 1, 1);"
631 "[].pop.call(obj);"
632 "[].pop.call(objNoCheck);");
633 // TODO(adamk): Extend EXPECT_RECORDS to be able to assert more things
634 // about splice records. For this test it's not so important since
635 // we just want to guarantee the machinery is in operation at all.
636 const RecordExpectation expected_records2[] = {
637 { obj_no_check, "splice", "", Handle<Value>() }
638 };
639 EXPECT_RECORDS(CompileRun("records2"), expected_records2);
640 } 793 }
641 const RecordExpectation expected_records[] = {
642 { obj_no_check, "splice", "", Handle<Value>() }
643 };
644 EXPECT_RECORDS(CompileRun("records"), expected_records);
645 } 794 }
646
647
648 TEST(DisallowAllForAccessKeys) {
649 HandleScope scope(CcTest::isolate());
650 LocalContext context(CcTest::isolate());
651 Handle<Object> instance = CreateAccessCheckedObject(
652 CcTest::isolate(), BlockAccessKeys, IndexedAccessAlwaysAllowed);
653 CompileRun("var records = null;"
654 "var objNoCheck = {};"
655 "var observer = function(r) { records = r };"
656 "Object.observe(obj, observer);"
657 "Object.observe(objNoCheck, observer);");
658 Handle<Value> obj_no_check = CompileRun("objNoCheck");
659 {
660 LocalContext context2(CcTest::isolate());
661 context2->Global()->Set(String::NewFromUtf8(CcTest::isolate(), "obj"),
662 instance);
663 context2->Global()->Set(
664 String::NewFromUtf8(CcTest::isolate(), "objNoCheck"), obj_no_check);
665 CompileRun("var records2 = null;"
666 "var observer2 = function(r) { records2 = r };"
667 "Object.observe(obj, observer2);"
668 "Object.observe(objNoCheck, observer2);"
669 "obj.foo = 'bar';"
670 "obj[5] = 'baz';"
671 "objNoCheck.baz = 'quux'");
672 const RecordExpectation expected_records2[] = {
673 { instance, "add", "foo", Handle<Value>() },
674 { instance, "add", "5", Handle<Value>() },
675 { obj_no_check, "add", "baz", Handle<Value>() },
676 };
677 EXPECT_RECORDS(CompileRun("records2"), expected_records2);
678 }
679 const RecordExpectation expected_records[] = {
680 { obj_no_check, "add", "baz", Handle<Value>() }
681 };
682 EXPECT_RECORDS(CompileRun("records"), expected_records);
683 }
684
685
686 TEST(AccessCheckDisallowApiModifications) {
687 HandleScope scope(CcTest::isolate());
688 LocalContext context(CcTest::isolate());
689 Handle<Object> instance = CreateAccessCheckedObject(
690 CcTest::isolate(), BlockAccessKeys, IndexedAccessAlwaysAllowed);
691 CompileRun("var records = null;"
692 "var observer = function(r) { records = r };"
693 "Object.observe(obj, observer);");
694 {
695 LocalContext context2(CcTest::isolate());
696 context2->Global()->Set(String::NewFromUtf8(CcTest::isolate(), "obj"),
697 instance);
698 CompileRun("var records2 = null;"
699 "var observer2 = function(r) { records2 = r };"
700 "Object.observe(obj, observer2);");
701 instance->Set(5, String::NewFromUtf8(CcTest::isolate(), "bar"));
702 instance->Set(String::NewFromUtf8(CcTest::isolate(), "foo"),
703 String::NewFromUtf8(CcTest::isolate(), "bar"));
704 CompileRun(""); // trigger delivery
705 const RecordExpectation expected_records2[] = {
706 { instance, "add", "5", Handle<Value>() },
707 { instance, "add", "foo", Handle<Value>() }
708 };
709 EXPECT_RECORDS(CompileRun("records2"), expected_records2);
710 }
711 CHECK(CompileRun("records")->IsNull());
712 }
713
714
715 TEST(HiddenPropertiesLeakage) {
716 HandleScope scope(CcTest::isolate());
717 LocalContext context(CcTest::isolate());
718 CompileRun("var obj = {};"
719 "var records = null;"
720 "var observer = function(r) { records = r };"
721 "Object.observe(obj, observer);");
722 Handle<Value> obj =
723 context->Global()->Get(String::NewFromUtf8(CcTest::isolate(), "obj"));
724 Handle<Object>::Cast(obj)
725 ->SetHiddenValue(String::NewFromUtf8(CcTest::isolate(), "foo"),
726 Null(CcTest::isolate()));
727 CompileRun(""); // trigger delivery
728 CHECK(CompileRun("records")->IsNull());
729 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698