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

Side by Side Diff: third_party/WebKit/Source/platform/heap/Handle.h

Issue 1430983002: [Oilpan] [NOCOMMIT] Add verifier in Member<> to detect use-after-free of on-heap objects. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Support GCMixin Created 5 years, 1 month 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
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2014 Google Inc. All rights reserved. 2 * Copyright (C) 2014 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 638 matching lines...) Expand 10 before | Expand all | Expand 10 after
649 public: 649 public:
650 PersistentHeapDeque() { } 650 PersistentHeapDeque() { }
651 651
652 template<size_t otherCapacity> 652 template<size_t otherCapacity>
653 PersistentHeapDeque(const HeapDeque<T, otherCapacity>& other) 653 PersistentHeapDeque(const HeapDeque<T, otherCapacity>& other)
654 : PersistentHeapCollectionBase<HeapDeque<T, inlineCapacity>>(other) 654 : PersistentHeapCollectionBase<HeapDeque<T, inlineCapacity>>(other)
655 { 655 {
656 } 656 }
657 }; 657 };
658 658
659 template<typename T, bool = IsGarbageCollectedMixin<T>::value> class GCMixinTrai t;
660 template<typename T>
661 class GCMixinTrait<T, true> {
662 public:
663 static HeapObjectHeader* heapObjectHeader(T* obj)
664 {
665 return obj->heapObjectHeader();
666 }
667 };
668 template<typename T>
669 class GCMixinTrait<T, false> {
670 public:
671 static HeapObjectHeader* heapObjectHeader(T* obj)
672 {
673 return HeapObjectHeader::fromPayload(obj);
674 }
675 };
676
659 // Members are used in classes to contain strong pointers to other oilpan heap 677 // Members are used in classes to contain strong pointers to other oilpan heap
660 // allocated objects. 678 // allocated objects.
661 // All Member fields of a class must be traced in the class' trace method. 679 // All Member fields of a class must be traced in the class' trace method.
662 // During the mark phase of the GC all live objects are marked as live and 680 // During the mark phase of the GC all live objects are marked as live and
663 // all Member fields of a live object will be traced marked as live as well. 681 // all Member fields of a live object will be traced marked as live as well.
664 template<typename T> 682 template<typename T>
665 class Member { 683 class Member {
666 public: 684 public:
667 Member() : m_raw(nullptr) 685 Member() : m_raw(nullptr)
668 { 686 {
687 checkPointer();
669 } 688 }
670 689
671 Member(std::nullptr_t) : m_raw(nullptr) 690 Member(std::nullptr_t) : m_raw(nullptr)
672 { 691 {
692 checkPointer();
673 } 693 }
674 694
675 Member(T* raw) : m_raw(raw) 695 Member(T* raw) : m_raw(raw)
676 { 696 {
677 checkPointer(); 697 checkPointer();
678 } 698 }
679 699
680 explicit Member(T& raw) : m_raw(&raw) 700 explicit Member(T& raw) : m_raw(&raw)
681 { 701 {
682 checkPointer(); 702 checkPointer();
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
755 Member& operator=(RawPtr<U> other) 775 Member& operator=(RawPtr<U> other)
756 { 776 {
757 m_raw = other; 777 m_raw = other;
758 checkPointer(); 778 checkPointer();
759 return *this; 779 return *this;
760 } 780 }
761 781
762 Member& operator=(std::nullptr_t) 782 Member& operator=(std::nullptr_t)
763 { 783 {
764 m_raw = nullptr; 784 m_raw = nullptr;
785 checkPointer();
765 return *this; 786 return *this;
766 } 787 }
767 788
768 void swap(Member<T>& other) 789 void swap(Member<T>& other)
769 { 790 {
770 std::swap(m_raw, other.m_raw); 791 std::swap(m_raw, other.m_raw);
771 checkPointer(); 792 checkPointer();
772 } 793 }
773 794
774 T* get() const { return m_raw; } 795 T* get() const
796 {
797 #if ENABLE(ASSERT)
798 if (m_raw && m_gcGeneration) {
799 ASSERT(m_gcGeneration == GCMixinTrait<T>::heapObjectHeader(m_raw)->g cGeneration());
800 }
801 #endif
802 return m_raw;
803 }
775 804
776 void clear() { m_raw = nullptr; } 805 // This method is an accessor without any security checks, and it is
806 // expected to be used under some limited condition.
807 // So do NOT use it, if you do not know what it means.
808 T* unsafeGet() const
809 {
810 return m_raw;
811 }
777 812
813 void clear()
814 {
815 m_raw = nullptr;
816 checkPointer();
817 }
778 818
779 protected: 819 protected:
780 void checkPointer() 820 void checkPointer()
781 { 821 {
782 #if ENABLE(ASSERT) 822 #if ENABLE(ASSERT)
783 if (!m_raw) 823 if (!m_raw) {
824 m_gcGeneration = 0;
784 return; 825 return;
826 }
785 // HashTable can store a special value (which is not aligned to the 827 // HashTable can store a special value (which is not aligned to the
786 // allocation granularity) to Member<> to represent a deleted entry. 828 // allocation granularity) to Member<> to represent a deleted entry.
787 // Thus we treat a pointer that is not aligned to the granularity 829 // Thus we treat a pointer that is not aligned to the granularity
788 // as a valid pointer. 830 // as a valid pointer.
789 if (reinterpret_cast<intptr_t>(m_raw) % allocationGranularity) 831 if (reinterpret_cast<intptr_t>(m_raw) % allocationGranularity)
790 return; 832 return;
791 833
792 // TODO(haraken): What we really want to check here is that the pointer 834 // TODO(haraken): What we really want to check here is that the pointer
793 // is a traceable object. In other words, the pointer is either of: 835 // is a traceable object. In other words, the pointer is either of:
794 // 836 //
795 // (a) a pointer to the head of an on-heap object. 837 // (a) a pointer to the head of an on-heap object.
796 // (b) a pointer to the head of an on-heap mixin object. 838 // (b) a pointer to the head of an on-heap mixin object.
797 // 839 //
798 // We can check it by calling Heap::isHeapObjectAlive(m_raw), 840 // We can check it by calling Heap::isHeapObjectAlive(m_raw),
799 // but we cannot call it here because it requires to include T.h. 841 // but we cannot call it here because it requires to include T.h.
800 // So we currently only try to implement the check for (a), but do 842 // So we currently only try to implement the check for (a), but do
801 // not insist that T's definition is in scope. 843 // not insist that T's definition is in scope.
802 if (IsFullyDefined<T>::value && !IsGarbageCollectedMixin<T>::value) 844 if (IsFullyDefined<T>::value) {
803 ASSERT(HeapObjectHeader::fromPayload(m_raw)->checkHeader()); 845 m_gcGeneration = GCMixinTrait<T>::heapObjectHeader(m_raw)->gcGenerat ion();
846 } else {
847 m_gcGeneration = 0;
848 }
804 #endif 849 #endif
805 } 850 }
806 851
807 T* m_raw; 852 T* m_raw;
808 853
854 #if ENABLE(ASSERT)
855 uint16_t m_gcGeneration;
856 #endif
857
809 template<bool x, WTF::WeakHandlingFlag y, WTF::ShouldWeakPointersBeMarkedStr ongly z, typename U, typename V> friend struct CollectionBackingTraceTrait; 858 template<bool x, WTF::WeakHandlingFlag y, WTF::ShouldWeakPointersBeMarkedStr ongly z, typename U, typename V> friend struct CollectionBackingTraceTrait;
810 friend class Visitor; 859 friend class Visitor;
811
812 }; 860 };
813 861
814 // WeakMember is similar to Member in that it is used to point to other oilpan 862 // WeakMember is similar to Member in that it is used to point to other oilpan
815 // heap allocated objects. 863 // heap allocated objects.
816 // However instead of creating a strong pointer to the object, the WeakMember cr eates 864 // However instead of creating a strong pointer to the object, the WeakMember cr eates
817 // a weak pointer, which does not keep the pointee alive. Hence if all pointers to 865 // a weak pointer, which does not keep the pointee alive. Hence if all pointers to
818 // to a heap allocated object are weak the object will be garbage collected. At the 866 // to a heap allocated object are weak the object will be garbage collected. At the
819 // time of GC the weak pointers will automatically be set to null. 867 // time of GC the weak pointers will automatically be set to null.
820 template<typename T> 868 template<typename T>
821 class WeakMember : public Member<T> { 869 class WeakMember : public Member<T> {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
862 WeakMember& operator=(const RawPtr<U>& other) 910 WeakMember& operator=(const RawPtr<U>& other)
863 { 911 {
864 this->m_raw = other; 912 this->m_raw = other;
865 this->checkPointer(); 913 this->checkPointer();
866 return *this; 914 return *this;
867 } 915 }
868 916
869 WeakMember& operator=(std::nullptr_t) 917 WeakMember& operator=(std::nullptr_t)
870 { 918 {
871 this->m_raw = nullptr; 919 this->m_raw = nullptr;
920 this->checkPointer();
872 return *this; 921 return *this;
873 } 922 }
874 923
875 private: 924 private:
876 T** cell() const { return const_cast<T**>(&this->m_raw); } 925 T** cell() const { return const_cast<T**>(&this->m_raw); }
877 926
878 template<typename Derived> friend class VisitorHelper; 927 template<typename Derived> friend class VisitorHelper;
879 }; 928 };
880 929
881 // UntracedMember is a pointer to an on-heap object that is not traced for some 930 // UntracedMember is a pointer to an on-heap object that is not traced for some
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
934 UntracedMember& operator=(const RawPtr<U>& other) 983 UntracedMember& operator=(const RawPtr<U>& other)
935 { 984 {
936 this->m_raw = other; 985 this->m_raw = other;
937 this->checkPointer(); 986 this->checkPointer();
938 return *this; 987 return *this;
939 } 988 }
940 989
941 UntracedMember& operator=(std::nullptr_t) 990 UntracedMember& operator=(std::nullptr_t)
942 { 991 {
943 this->m_raw = nullptr; 992 this->m_raw = nullptr;
993 this->checkPointer();
944 return *this; 994 return *this;
945 } 995 }
946 }; 996 };
947 997
948 // Comparison operators between (Weak)Members, Persistents, and UntracedMembers. 998 // Comparison operators between (Weak)Members, Persistents, and UntracedMembers.
949 template<typename T, typename U> inline bool operator==(const Member<T>& a, cons t Member<U>& b) { return a.get() == b.get(); } 999 template<typename T, typename U> inline bool operator==(const Member<T>& a, cons t Member<U>& b) { return a.unsafeGet() == b.unsafeGet(); }
950 template<typename T, typename U> inline bool operator!=(const Member<T>& a, cons t Member<U>& b) { return a.get() != b.get(); } 1000 template<typename T, typename U> inline bool operator!=(const Member<T>& a, cons t Member<U>& b) { return a.unsafeGet() != b.unsafeGet(); }
951 template<typename T, typename U> inline bool operator==(const Persistent<T>& a, const Persistent<U>& b) { return a.get() == b.get(); } 1001 template<typename T, typename U> inline bool operator==(const Persistent<T>& a, const Persistent<U>& b) { return a.get() == b.get(); }
952 template<typename T, typename U> inline bool operator!=(const Persistent<T>& a, const Persistent<U>& b) { return a.get() != b.get(); } 1002 template<typename T, typename U> inline bool operator!=(const Persistent<T>& a, const Persistent<U>& b) { return a.get() != b.get(); }
953 1003
954 template<typename T, typename U> inline bool operator==(const Member<T>& a, cons t Persistent<U>& b) { return a.get() == b.get(); } 1004 template<typename T, typename U> inline bool operator==(const Member<T>& a, cons t Persistent<U>& b) { return a.get() == b.get(); }
955 template<typename T, typename U> inline bool operator!=(const Member<T>& a, cons t Persistent<U>& b) { return a.get() != b.get(); } 1005 template<typename T, typename U> inline bool operator!=(const Member<T>& a, cons t Persistent<U>& b) { return a.get() != b.get(); }
956 template<typename T, typename U> inline bool operator==(const Persistent<T>& a, const Member<U>& b) { return a.get() == b.get(); } 1006 template<typename T, typename U> inline bool operator==(const Persistent<T>& a, const Member<U>& b) { return a.get() == b.get(); }
957 template<typename T, typename U> inline bool operator!=(const Persistent<T>& a, const Member<U>& b) { return a.get() != b.get(); } 1007 template<typename T, typename U> inline bool operator!=(const Persistent<T>& a, const Member<U>& b) { return a.get() != b.get(); }
958 1008
959 template<typename T> 1009 template<typename T>
960 class DummyBase { 1010 class DummyBase {
(...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after
1407 1457
1408 template<typename T> struct PtrHash<blink::Member<T>> : PtrHash<T*> { 1458 template<typename T> struct PtrHash<blink::Member<T>> : PtrHash<T*> {
1409 template<typename U> 1459 template<typename U>
1410 static unsigned hash(const U& key) { return PtrHash<T*>::hash(key); } 1460 static unsigned hash(const U& key) { return PtrHash<T*>::hash(key); }
1411 static bool equal(T* a, const blink::Member<T>& b) { return a == b; } 1461 static bool equal(T* a, const blink::Member<T>& b) { return a == b; }
1412 static bool equal(const blink::Member<T>& a, T* b) { return a == b; } 1462 static bool equal(const blink::Member<T>& a, T* b) { return a == b; }
1413 template<typename U, typename V> 1463 template<typename U, typename V>
1414 static bool equal(const U& a, const V& b) { return a == b; } 1464 static bool equal(const U& a, const V& b) { return a == b; }
1415 }; 1465 };
1416 1466
1417 template<typename T> struct PtrHash<blink::WeakMember<T>> : PtrHash<blink::Membe r<T>> { 1467 template<typename T> struct PtrHash<blink::WeakMember<T>> : PtrHash<blink::Membe r<T>> { };
1418 };
1419 1468
1420 template<typename T> struct PtrHash<blink::UntracedMember<T>> : PtrHash<blink::M ember<T>> { 1469 template<typename T> struct PtrHash<blink::UntracedMember<T>> : PtrHash<blink::M ember<T>> { };
1421 };
1422 1470
1423 // PtrHash is the default hash for hash tables with members. 1471 // PtrHash is the default hash for hash tables with members.
1424 template<typename T> struct DefaultHash<blink::Member<T>> { 1472 template<typename T> struct DefaultHash<blink::Member<T>> {
1425 using Hash = PtrHash<blink::Member<T>>; 1473 using Hash = PtrHash<blink::Member<T>>;
1426 }; 1474 };
1427 1475
1428 template<typename T> struct DefaultHash<blink::WeakMember<T>> { 1476 template<typename T> struct DefaultHash<blink::WeakMember<T>> {
1429 using Hash = PtrHash<blink::WeakMember<T>>; 1477 using Hash = PtrHash<blink::WeakMember<T>>;
1430 }; 1478 };
1431 1479
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
1504 // TODO(sof): extend WTF::FunctionWrapper call overloading to also handle (C rossThread)WeakPersistent. 1552 // TODO(sof): extend WTF::FunctionWrapper call overloading to also handle (C rossThread)WeakPersistent.
1505 static T* unwrap(const StorageType& value) { return value.get(); } 1553 static T* unwrap(const StorageType& value) { return value.get(); }
1506 }; 1554 };
1507 1555
1508 template<typename T> 1556 template<typename T>
1509 PassRefPtr<T> adoptRef(blink::RefCountedGarbageCollected<T>*) = delete; 1557 PassRefPtr<T> adoptRef(blink::RefCountedGarbageCollected<T>*) = delete;
1510 1558
1511 } // namespace WTF 1559 } // namespace WTF
1512 1560
1513 #endif 1561 #endif
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/platform/heap/GarbageCollected.h ('k') | third_party/WebKit/Source/platform/heap/Heap.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698