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

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

Issue 1411603007: [Oilpan] Add use-after-free detector in Member<> Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 5 years 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 753 matching lines...) Expand 10 before | Expand all | Expand 10 after
764 m_raw = nullptr; 764 m_raw = nullptr;
765 return *this; 765 return *this;
766 } 766 }
767 767
768 void swap(Member<T>& other) 768 void swap(Member<T>& other)
769 { 769 {
770 std::swap(m_raw, other.m_raw); 770 std::swap(m_raw, other.m_raw);
771 checkPointer(); 771 checkPointer();
772 } 772 }
773 773
774 T* get() const { return m_raw; } 774 T* get() const
775 {
776 #if ENABLE(ASSERT) && defined(ADDRESS_SANITIZER)
777 // Verify that this handle points to a live on-heap object, if a pointer
778 // has been assigned to this handle out of GarbageCollectedMixin constru ctions.
779 if (m_raw && m_gcGeneration != gcGenerationUnchecked && !ThreadState::cu rrent()->isConstructingGCMixin()) {
780 HeapObjectHeader* header = heapObjectHeader();
781 ASSERT(m_gcGeneration == header->gcGeneration());
782 }
783 #endif
784 return m_raw;
785 }
786
787 // This method is an accessor without any security checks, and it is
788 // expected to be used under some limited condition.
789 // So do NOT use it, if you do not know what it means.
790 // TODO(peria): We should remove this method.
791 T* unsafeGet() const
792 {
793 return m_raw;
794 }
775 795
776 void clear() { m_raw = nullptr; } 796 void clear() { m_raw = nullptr; }
777 797
798 protected:
799 #if ENABLE(ASSERT) && defined(ADDRESS_SANITIZER)
800 HeapObjectHeader* heapObjectHeader() const
801 {
802 BasePage* page = pageFromObject(m_raw);
803 if (page->isLargeObjectPage()) {
804 LargeObjectPage* large = static_cast<LargeObjectPage*>(page);
805 return large->heapObjectHeader();
806 }
807 NormalPage* normal = static_cast<NormalPage*>(page);
808 return normal->findHeaderFromObject(m_raw);
809 }
810 #endif
778 811
779 protected:
780 void checkPointer() 812 void checkPointer()
781 { 813 {
782 #if ENABLE(ASSERT) && defined(ADDRESS_SANITIZER) 814 #if ENABLE(ASSERT) && defined(ADDRESS_SANITIZER)
783 if (!m_raw) 815 if (!m_raw)
784 return; 816 return;
785 // HashTable can store a special value (which is not aligned to the 817 // HashTable can store a special value (which is not aligned to the
786 // allocation granularity) to Member<> to represent a deleted entry. 818 // allocation granularity) to Member<> to represent a deleted entry.
787 // Thus we treat a pointer that is not aligned to the granularity 819 // Thus we treat a pointer that is not aligned to the granularity
788 // as a valid pointer. 820 // as a valid pointer.
789 if (reinterpret_cast<intptr_t>(m_raw) % allocationGranularity) 821 if (reinterpret_cast<intptr_t>(m_raw) % allocationGranularity)
790 return; 822 return;
791 823
792 // TODO(haraken): What we really want to check here is that the pointer 824 // m_gcGeneration verifies use-after-free of this Member handle.
793 // is a traceable object. In other words, the pointer is either of: 825 // If m_gcGeneration is gcGenerationUnchecked or m_raw is nullptr,
794 // 826 // the verification is skipped.
795 // (a) a pointer to the head of an on-heap object. 827 // We set gcGenerationUnchecked while constructing a GC mixin object
796 // (b) a pointer to the head of an on-heap mixin object. 828 // (and skip the verification unfortunately) because
797 // 829 // HeapObjectHeaderTrait<T>::heapObjectHeader doesn't work before
798 // We can check it by calling Heap::isHeapObjectAlive(m_raw), 830 // the vtable of the object is complete.
799 // but we cannot call it here because it requires to include T.h. 831 // FIXME(Oilpan): We want to check them, too.
800 // So we currently only try to implement the check for (a), but do 832 m_gcGeneration = gcGenerationUnchecked;
801 // not insist that T's definition is in scope. 833 if (!ThreadState::current()->isConstructingGCMixin()) {
802 if (IsFullyDefined<T>::value && !IsGarbageCollectedMixin<T>::value) 834 HeapObjectHeader* header = heapObjectHeader();
803 ASSERT(HeapObjectHeader::fromPayload(m_raw)->checkHeader()); 835 m_gcGeneration = header->gcGeneration();
836 ASSERT(m_gcGeneration != gcGenerationForFreeListEntry);
837 }
804 #endif 838 #endif
805 } 839 }
806 840
807 T* m_raw; 841 T* m_raw;
808 842
843 #if ENABLE(ASSERT) && defined(ADDRESS_SANITIZER)
844 uint32_t m_gcGeneration;
845 #endif
846
809 template<bool x, WTF::WeakHandlingFlag y, WTF::ShouldWeakPointersBeMarkedStr ongly z, typename U, typename V> friend struct CollectionBackingTraceTrait; 847 template<bool x, WTF::WeakHandlingFlag y, WTF::ShouldWeakPointersBeMarkedStr ongly z, typename U, typename V> friend struct CollectionBackingTraceTrait;
810 friend class Visitor; 848 friend class Visitor;
811
812 }; 849 };
813 850
814 // WeakMember is similar to Member in that it is used to point to other oilpan 851 // WeakMember is similar to Member in that it is used to point to other oilpan
815 // heap allocated objects. 852 // heap allocated objects.
816 // However instead of creating a strong pointer to the object, the WeakMember cr eates 853 // 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 854 // 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 855 // 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. 856 // time of GC the weak pointers will automatically be set to null.
820 template<typename T> 857 template<typename T>
821 class WeakMember : public Member<T> { 858 class WeakMember : public Member<T> {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
865 this->checkPointer(); 902 this->checkPointer();
866 return *this; 903 return *this;
867 } 904 }
868 905
869 WeakMember& operator=(std::nullptr_t) 906 WeakMember& operator=(std::nullptr_t)
870 { 907 {
871 this->m_raw = nullptr; 908 this->m_raw = nullptr;
872 return *this; 909 return *this;
873 } 910 }
874 911
912 // TODO(peria): Remove this get() and use unsafeGet() at only
913 // where it is required.
914 T* get() const
915 {
916 // WeakMember may point to a dead object, so we skip the verification.
917 return Member<T>::unsafeGet();
918 }
919
875 private: 920 private:
876 T** cell() const { return const_cast<T**>(&this->m_raw); } 921 T** cell() const { return const_cast<T**>(&this->m_raw); }
877 922
878 template<typename Derived> friend class VisitorHelper; 923 template<typename Derived> friend class VisitorHelper;
879 }; 924 };
880 925
881 // UntracedMember is a pointer to an on-heap object that is not traced for some 926 // UntracedMember is a pointer to an on-heap object that is not traced for some
882 // reason. Please don't use this unless you understand what you're doing. 927 // reason. Please don't use this unless you understand what you're doing.
883 // Basically, all pointers to on-heap objects must be stored in either of 928 // Basically, all pointers to on-heap objects must be stored in either of
884 // Persistent, Member or WeakMember. It is not allowed to leave raw pointers to 929 // Persistent, Member or WeakMember. It is not allowed to leave raw pointers to
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
939 } 984 }
940 985
941 UntracedMember& operator=(std::nullptr_t) 986 UntracedMember& operator=(std::nullptr_t)
942 { 987 {
943 this->m_raw = nullptr; 988 this->m_raw = nullptr;
944 return *this; 989 return *this;
945 } 990 }
946 }; 991 };
947 992
948 // Comparison operators between (Weak)Members, Persistents, and UntracedMembers. 993 // 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(); } 994 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(); } 995 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(); } 996 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(); } 997 template<typename T, typename U> inline bool operator!=(const Persistent<T>& a, const Persistent<U>& b) { return a.get() != b.get(); }
953 998
954 template<typename T, typename U> inline bool operator==(const Member<T>& a, cons t Persistent<U>& b) { return a.get() == b.get(); } 999 template<typename T, typename U> inline bool operator==(const Member<T>& a, cons t Persistent<U>& b) { return a.unsafeGet() == 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(); } 1000 template<typename T, typename U> inline bool operator!=(const Member<T>& a, cons t Persistent<U>& b) { return a.unsafeGet() != b.get(); }
956 template<typename T, typename U> inline bool operator==(const Persistent<T>& a, const Member<U>& b) { return a.get() == b.get(); } 1001 template<typename T, typename U> inline bool operator==(const Persistent<T>& a, const Member<U>& b) { return a.get() == b.unsafeGet(); }
957 template<typename T, typename U> inline bool operator!=(const Persistent<T>& a, const Member<U>& b) { return a.get() != b.get(); } 1002 template<typename T, typename U> inline bool operator!=(const Persistent<T>& a, const Member<U>& b) { return a.get() != b.unsafeGet(); }
958 1003
959 template<typename T> 1004 template<typename T>
960 class DummyBase { 1005 class DummyBase {
961 public: 1006 public:
962 DummyBase() { } 1007 DummyBase() { }
963 ~DummyBase() { } 1008 ~DummyBase() { }
964 }; 1009 };
965 1010
966 // We need this explicit instantiation for component build on Windows. 1011 // We need this explicit instantiation for component build on Windows.
967 template<> 1012 template<>
(...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after
1407 1452
1408 template<typename T> struct PtrHash<blink::Member<T>> : PtrHash<T*> { 1453 template<typename T> struct PtrHash<blink::Member<T>> : PtrHash<T*> {
1409 template<typename U> 1454 template<typename U>
1410 static unsigned hash(const U& key) { return PtrHash<T*>::hash(key); } 1455 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; } 1456 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; } 1457 static bool equal(const blink::Member<T>& a, T* b) { return a == b; }
1413 template<typename U, typename V> 1458 template<typename U, typename V>
1414 static bool equal(const U& a, const V& b) { return a == b; } 1459 static bool equal(const U& a, const V& b) { return a == b; }
1415 }; 1460 };
1416 1461
1417 template<typename T> struct PtrHash<blink::WeakMember<T>> : PtrHash<blink::Membe r<T>> { 1462 template<typename T> struct PtrHash<blink::WeakMember<T>> : PtrHash<blink::Membe r<T>> { };
1418 };
1419 1463
1420 template<typename T> struct PtrHash<blink::UntracedMember<T>> : PtrHash<blink::M ember<T>> { 1464 template<typename T> struct PtrHash<blink::UntracedMember<T>> : PtrHash<blink::M ember<T>> { };
1421 };
1422 1465
1423 // PtrHash is the default hash for hash tables with members. 1466 // PtrHash is the default hash for hash tables with members.
1424 template<typename T> struct DefaultHash<blink::Member<T>> { 1467 template<typename T> struct DefaultHash<blink::Member<T>> {
1425 using Hash = PtrHash<blink::Member<T>>; 1468 using Hash = PtrHash<blink::Member<T>>;
1426 }; 1469 };
1427 1470
1428 template<typename T> struct DefaultHash<blink::WeakMember<T>> { 1471 template<typename T> struct DefaultHash<blink::WeakMember<T>> {
1429 using Hash = PtrHash<blink::WeakMember<T>>; 1472 using Hash = PtrHash<blink::WeakMember<T>>;
1430 }; 1473 };
1431 1474
(...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. 1547 // TODO(sof): extend WTF::FunctionWrapper call overloading to also handle (C rossThread)WeakPersistent.
1505 static T* unwrap(const StorageType& value) { return value.get(); } 1548 static T* unwrap(const StorageType& value) { return value.get(); }
1506 }; 1549 };
1507 1550
1508 template<typename T> 1551 template<typename T>
1509 PassRefPtr<T> adoptRef(blink::RefCountedGarbageCollected<T>*) = delete; 1552 PassRefPtr<T> adoptRef(blink::RefCountedGarbageCollected<T>*) = delete;
1510 1553
1511 } // namespace WTF 1554 } // namespace WTF
1512 1555
1513 #endif 1556 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698