Chromium Code Reviews| 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 |