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

Side by Side Diff: src/keys.cc

Issue 2087823002: Optionally invoke an interceptor on failed access checks (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: updates Created 4 years, 5 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
« no previous file with comments | « src/isolate.cc ('k') | src/lookup.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/keys.h" 5 #include "src/keys.h"
6 6
7 #include "src/api-arguments.h" 7 #include "src/api-arguments.h"
8 #include "src/elements.h" 8 #include "src/elements.h"
9 #include "src/factory.h" 9 #include "src/factory.h"
10 #include "src/identity-map.h" 10 #include "src/identity-map.h"
(...skipping 416 matching lines...) Expand 10 before | Expand all | Expand 10 after
427 namespace { 427 namespace {
428 428
429 enum IndexedOrNamed { kIndexed, kNamed }; 429 enum IndexedOrNamed { kIndexed, kNamed };
430 430
431 // Returns |true| on success, |nothing| on exception. 431 // Returns |true| on success, |nothing| on exception.
432 template <class Callback, IndexedOrNamed type> 432 template <class Callback, IndexedOrNamed type>
433 Maybe<bool> CollectInterceptorKeys(Handle<JSReceiver> receiver, 433 Maybe<bool> CollectInterceptorKeys(Handle<JSReceiver> receiver,
434 Handle<JSObject> object, 434 Handle<JSObject> object,
435 KeyAccumulator* accumulator) { 435 KeyAccumulator* accumulator) {
436 Isolate* isolate = accumulator->isolate(); 436 Isolate* isolate = accumulator->isolate();
437 if (type == kIndexed) { 437 Handle<InterceptorInfo> interceptor;
438 if (!object->HasIndexedInterceptor()) return Just(true); 438 if ((accumulator->filter() & USE_ACCESS_CHECK_INTERCEPTOR) &&
439 object->IsAccessCheckNeeded()) {
440 DisallowHeapAllocation no_gc;
441 AccessCheckInfo* access_check_info = AccessCheckInfo::Get(isolate, object);
442 if (!access_check_info) return Just(true);
443 Object* maybe_interceptor = type == kIndexed
444 ? access_check_info->indexed_interceptor()
445 : access_check_info->named_interceptor();
446 if (!maybe_interceptor) return Just(true);
447 interceptor = handle(InterceptorInfo::cast(maybe_interceptor), isolate);
439 } else { 448 } else {
440 if (!object->HasNamedInterceptor()) return Just(true); 449 if (type == kIndexed) {
441 } 450 if (!object->HasIndexedInterceptor()) return Just(true);
442 Handle<InterceptorInfo> interceptor(type == kIndexed 451 } else {
443 ? object->GetIndexedInterceptor() 452 if (!object->HasNamedInterceptor()) return Just(true);
453 }
454 interceptor = handle(type == kIndexed ? object->GetIndexedInterceptor()
444 : object->GetNamedInterceptor(), 455 : object->GetNamedInterceptor(),
445 isolate); 456 isolate);
446 if ((accumulator->filter() & ONLY_ALL_CAN_READ) && 457 if ((accumulator->filter() & ONLY_ALL_CAN_READ) &&
447 !interceptor->all_can_read()) { 458 !interceptor->all_can_read()) {
448 return Just(true); 459 return Just(true);
460 }
449 } 461 }
450 PropertyCallbackArguments args(isolate, interceptor->data(), *receiver, 462 PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
451 *object, Object::DONT_THROW); 463 *object, Object::DONT_THROW);
452 Handle<JSObject> result; 464 Handle<JSObject> result;
453 if (!interceptor->enumerator()->IsUndefined(isolate)) { 465 if (!interceptor->enumerator()->IsUndefined(isolate)) {
454 Callback enum_fun = v8::ToCData<Callback>(interceptor->enumerator()); 466 Callback enum_fun = v8::ToCData<Callback>(interceptor->enumerator());
455 const char* log_tag = type == kIndexed ? "interceptor-indexed-enum" 467 const char* log_tag = type == kIndexed ? "interceptor-indexed-enum"
456 : "interceptor-named-enum"; 468 : "interceptor-named-enum";
457 LOG(isolate, ApiObjectAccess(log_tag, *object)); 469 LOG(isolate, ApiObjectAccess(log_tag, *object));
458 result = args.Call(enum_fun); 470 result = args.Call(enum_fun);
(...skipping 18 matching lines...) Expand all
477 kIndexed>(receiver, object, this); 489 kIndexed>(receiver, object, this);
478 } 490 }
479 491
480 namespace { 492 namespace {
481 493
482 template <bool skip_symbols> 494 template <bool skip_symbols>
483 int CollectOwnPropertyNamesInternal(Handle<JSObject> object, 495 int CollectOwnPropertyNamesInternal(Handle<JSObject> object,
484 KeyAccumulator* keys, 496 KeyAccumulator* keys,
485 Handle<DescriptorArray> descs, 497 Handle<DescriptorArray> descs,
486 int start_index, int limit) { 498 int start_index, int limit) {
499 DCHECK(!(keys->filter() & USE_ACCESS_CHECK_INTERCEPTOR));
487 int first_skipped = -1; 500 int first_skipped = -1;
488 for (int i = start_index; i < limit; i++) { 501 for (int i = start_index; i < limit; i++) {
489 PropertyDetails details = descs->GetDetails(i); 502 PropertyDetails details = descs->GetDetails(i);
490 if ((details.attributes() & keys->filter()) != 0) continue; 503 if ((details.attributes() & keys->filter()) != 0) continue;
491 if (keys->filter() & ONLY_ALL_CAN_READ) { 504 if (keys->filter() & ONLY_ALL_CAN_READ) {
492 if (details.kind() != kAccessor) continue; 505 if (details.kind() != kAccessor) continue;
493 Object* accessors = descs->GetValue(i); 506 Object* accessors = descs->GetValue(i);
494 if (!accessors->IsAccessorInfo()) continue; 507 if (!accessors->IsAccessorInfo()) continue;
495 if (!AccessorInfo::cast(accessors)->all_can_read()) continue; 508 if (!AccessorInfo::cast(accessors)->all_can_read()) continue;
496 } 509 }
497 Name* key = descs->GetKey(i); 510 Name* key = descs->GetKey(i);
498 if (skip_symbols == key->IsSymbol()) { 511 if (skip_symbols == key->IsSymbol()) {
499 if (first_skipped == -1) first_skipped = i; 512 if (first_skipped == -1) first_skipped = i;
500 continue; 513 continue;
501 } 514 }
502 if (key->FilterKey(keys->filter())) continue; 515 if (key->FilterKey(keys->filter())) continue;
503 keys->AddKey(key, DO_NOT_CONVERT); 516 keys->AddKey(key, DO_NOT_CONVERT);
504 } 517 }
505 return first_skipped; 518 return first_skipped;
506 } 519 }
507 520
508 } // namespace 521 } // namespace
509 522
510 Maybe<bool> KeyAccumulator::CollectOwnPropertyNames(Handle<JSReceiver> receiver, 523 Maybe<bool> KeyAccumulator::CollectOwnPropertyNames(Handle<JSReceiver> receiver,
511 Handle<JSObject> object) { 524 Handle<JSObject> object) {
512 if (filter_ == ENUMERABLE_STRINGS) { 525 if (filter_ == ENUMERABLE_STRINGS) {
513 Handle<FixedArray> enum_keys = 526 Handle<FixedArray> enum_keys =
514 KeyAccumulator::GetEnumPropertyKeys(isolate_, object); 527 KeyAccumulator::GetEnumPropertyKeys(isolate_, object);
515 AddKeys(enum_keys, DO_NOT_CONVERT); 528 AddKeys(enum_keys, DO_NOT_CONVERT);
516 } else { 529 } else if (!(filter_ & USE_ACCESS_CHECK_INTERCEPTOR)) {
517 if (object->HasFastProperties()) { 530 if (object->HasFastProperties()) {
518 int limit = object->map()->NumberOfOwnDescriptors(); 531 int limit = object->map()->NumberOfOwnDescriptors();
519 Handle<DescriptorArray> descs(object->map()->instance_descriptors(), 532 Handle<DescriptorArray> descs(object->map()->instance_descriptors(),
520 isolate_); 533 isolate_);
521 // First collect the strings, 534 // First collect the strings,
522 int first_symbol = 535 int first_symbol =
523 CollectOwnPropertyNamesInternal<true>(object, this, descs, 0, limit); 536 CollectOwnPropertyNamesInternal<true>(object, this, descs, 0, limit);
524 // then the symbols. 537 // then the symbols.
525 if (first_symbol != -1) { 538 if (first_symbol != -1) {
526 CollectOwnPropertyNamesInternal<false>(object, this, descs, 539 CollectOwnPropertyNamesInternal<false>(object, this, descs,
(...skipping 12 matching lines...) Expand all
539 kNamed>(receiver, object, this); 552 kNamed>(receiver, object, this);
540 } 553 }
541 554
542 // Returns |true| on success, |false| if prototype walking should be stopped, 555 // Returns |true| on success, |false| if prototype walking should be stopped,
543 // |nothing| if an exception was thrown. 556 // |nothing| if an exception was thrown.
544 Maybe<bool> KeyAccumulator::CollectOwnKeys(Handle<JSReceiver> receiver, 557 Maybe<bool> KeyAccumulator::CollectOwnKeys(Handle<JSReceiver> receiver,
545 Handle<JSObject> object) { 558 Handle<JSObject> object) {
546 // Check access rights if required. 559 // Check access rights if required.
547 if (object->IsAccessCheckNeeded() && 560 if (object->IsAccessCheckNeeded() &&
548 !isolate_->MayAccess(handle(isolate_->context()), object)) { 561 !isolate_->MayAccess(handle(isolate_->context()), object)) {
562 DisallowHeapAllocation no_gc;
563
549 // The cross-origin spec says that [[Enumerate]] shall return an empty 564 // The cross-origin spec says that [[Enumerate]] shall return an empty
550 // iterator when it doesn't have access... 565 // iterator when it doesn't have access...
551 if (mode_ == KeyCollectionMode::kIncludePrototypes) { 566 if (mode_ == KeyCollectionMode::kIncludePrototypes) {
552 return Just(false); 567 return Just(false);
553 } 568 }
554 // ...whereas [[OwnPropertyKeys]] shall return whitelisted properties. 569 // ...whereas [[OwnPropertyKeys]] shall return whitelisted properties.
555 DCHECK(KeyCollectionMode::kOwnOnly == mode_); 570 DCHECK(KeyCollectionMode::kOwnOnly == mode_);
556 filter_ = static_cast<PropertyFilter>(filter_ | ONLY_ALL_CAN_READ); 571 AccessCheckInfo* access_check_info = AccessCheckInfo::Get(isolate_, object);
572 // We always either have both a named and an indexed interceptor or none.
573 if (!access_check_info || !access_check_info->named_interceptor()) {
574 filter_ = static_cast<PropertyFilter>(filter_ | ONLY_ALL_CAN_READ);
575 } else {
576 filter_ =
577 static_cast<PropertyFilter>(filter_ | USE_ACCESS_CHECK_INTERCEPTOR);
Toon Verwaest 2016/06/27 09:34:58 We should get rid of these filters. Just duplicate
Toon Verwaest 2016/06/27 09:37:59 I think you basically want to reuse the lower half
578 }
557 } 579 }
558 MAYBE_RETURN(CollectOwnElementIndices(receiver, object), Nothing<bool>()); 580 MAYBE_RETURN(CollectOwnElementIndices(receiver, object), Nothing<bool>());
559 MAYBE_RETURN(CollectOwnPropertyNames(receiver, object), Nothing<bool>()); 581 MAYBE_RETURN(CollectOwnPropertyNames(receiver, object), Nothing<bool>());
560 return Just(true); 582 return Just(true);
561 } 583 }
562 584
563 // static 585 // static
564 Handle<FixedArray> KeyAccumulator::GetEnumPropertyKeys( 586 Handle<FixedArray> KeyAccumulator::GetEnumPropertyKeys(
565 Isolate* isolate, Handle<JSObject> object) { 587 Isolate* isolate, Handle<JSObject> object) {
588 DCHECK(!object->IsAccessCheckNeeded() ||
589 isolate->MayAccess(handle(isolate->context()), object));
566 if (object->HasFastProperties()) { 590 if (object->HasFastProperties()) {
567 return GetFastEnumPropertyKeys(isolate, object); 591 return GetFastEnumPropertyKeys(isolate, object);
568 } else if (object->IsJSGlobalObject()) { 592 } else if (object->IsJSGlobalObject()) {
569 Handle<GlobalDictionary> dictionary(object->global_dictionary(), isolate); 593 Handle<GlobalDictionary> dictionary(object->global_dictionary(), isolate);
570 int length = dictionary->NumberOfEnumElements(); 594 int length = dictionary->NumberOfEnumElements();
571 if (length == 0) { 595 if (length == 0) {
572 return isolate->factory()->empty_fixed_array(); 596 return isolate->factory()->empty_fixed_array();
573 } 597 }
574 Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length); 598 Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length);
575 dictionary->CopyEnumKeysTo(*storage); 599 dictionary->CopyEnumKeysTo(*storage);
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
741 isolate_, keys, JSReceiver::OwnPropertyKeys(target), Nothing<bool>()); 765 isolate_, keys, JSReceiver::OwnPropertyKeys(target), Nothing<bool>());
742 bool prev_filter_proxy_keys_ = filter_proxy_keys_; 766 bool prev_filter_proxy_keys_ = filter_proxy_keys_;
743 filter_proxy_keys_ = false; 767 filter_proxy_keys_ = false;
744 Maybe<bool> result = AddKeysFromJSProxy(proxy, keys); 768 Maybe<bool> result = AddKeysFromJSProxy(proxy, keys);
745 filter_proxy_keys_ = prev_filter_proxy_keys_; 769 filter_proxy_keys_ = prev_filter_proxy_keys_;
746 return result; 770 return result;
747 } 771 }
748 772
749 } // namespace internal 773 } // namespace internal
750 } // namespace v8 774 } // namespace v8
OLDNEW
« no previous file with comments | « src/isolate.cc ('k') | src/lookup.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698