OLD | NEW |
---|---|
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 Loading... | |
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 } | |
OLD | NEW |