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

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: Require full definition of T 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 756 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 774 T* get() const
775 { 775 {
776 static_assert(IsFullyDefined<T>::value, "T is not fully defined."); 776 static_assert(IsFullyDefined<T>::value, "T is not fully defined.");
777 #if ENABLE(ASSERT) && defined(ADDRESS_SANITIZER)
778 // Verify that this handle points to a live on-heap object, if a pointer
779 // has been assigned to this handle out of GarbageCollectedMixin constru ctions.
780 if (m_raw && m_gcGeneration != gcGenerationUnchecked && !ThreadState::cu rrent()->isConstructingGCMixin()) {
781 HeapObjectHeader* header = HeapObjectHeaderTrait<T>::heapObjectHeade r(m_raw);
782 ASSERT(m_gcGeneration == header->gcGeneration());
783 }
784 #endif
777 return m_raw; 785 return m_raw;
778 } 786 }
779 787
780 void clear() { m_raw = nullptr; } 788 // This method is an accessor without any security checks, and it is
789 // expected to be used under some limited condition.
790 // So do NOT use it, if you do not know what it means.
791 // TODO(peria): We should remove this method.
792 T* unsafeGet() const
793 {
794 return m_raw;
795 }
781 796
797 void clear()
798 {
799 m_raw = nullptr;
800 }
782 801
783 protected: 802 protected:
784 void checkPointer() 803 void checkPointer()
haraken 2015/11/20 01:59:06 In a follow-up CL, can you rename this to setPoint
peria 2015/11/20 02:27:00 Acknowledged.
785 { 804 {
786 static_assert(IsFullyDefined<T>::value, "T is not fully defined."); 805 static_assert(IsFullyDefined<T>::value, "T is not fully defined.");
787 806
788 #if ENABLE(ASSERT) && defined(ADDRESS_SANITIZER) 807 #if ENABLE(ASSERT) && defined(ADDRESS_SANITIZER)
789 if (!m_raw) 808 if (!m_raw)
790 return; 809 return;
791 // HashTable can store a special value (which is not aligned to the 810 // HashTable can store a special value (which is not aligned to the
792 // allocation granularity) to Member<> to represent a deleted entry. 811 // allocation granularity) to Member<> to represent a deleted entry.
793 // Thus we treat a pointer that is not aligned to the granularity 812 // Thus we treat a pointer that is not aligned to the granularity
794 // as a valid pointer. 813 // as a valid pointer.
795 if (reinterpret_cast<intptr_t>(m_raw) % allocationGranularity) 814 if (reinterpret_cast<intptr_t>(m_raw) % allocationGranularity)
796 return; 815 return;
797 816
798 // TODO(haraken): What we really want to check here is that the pointer 817 // m_gcGeneration verifies use-after-free of this Member handle.
799 // is a traceable object. In other words, the pointer is either of: 818 // If m_gcGeneration is gcGenerationForFreeListEntry or m_raw is
800 // 819 // nullptr, the verification is skipped.
haraken 2015/11/20 01:59:06 gcGenerationForFreeListEntry => gcGenerationUnchec
peria 2015/11/20 02:27:00 Done.
801 // (a) a pointer to the head of an on-heap object. 820 // For technical reason, we set gcGenerationForFreeListEntry in
802 // (b) a pointer to the head of an on-heap mixin object. 821 // m_gcGeneration in case that this method is called in a constructor
803 // 822 // of a GCMixin object.
haraken 2015/11/20 01:59:06 We set gcGenerationUnchecked while constructing a
peria 2015/11/20 04:14:50 Done.
804 // We can check it by calling Heap::isHeapObjectAlive(m_raw), 823 // TODO(peria): Set m_gcGeneration even if this is called in a
805 // but we cannot call it here because it requires to include T.h. 824 // GCMixin constructor.
806 // So we currently only try to implement the check for (a), but do 825 m_gcGeneration = gcGenerationUnchecked;
807 // not insist that T's definition is in scope. 826 if (IsFullyDefined<T>::value && !ThreadState::current()->isConstructingG CMixin()) {
haraken 2015/11/20 01:59:06 Remove the IsFullyDefined<T>::value check. As we d
peria 2015/11/20 02:27:00 Done. And it is checked statically at the beginnin
808 if (IsFullyDefined<T>::value && !IsGarbageCollectedMixin<T>::value) 827 HeapObjectHeader* header = HeapObjectHeaderTrait<T>::heapObjectHeade r(m_raw);
809 ASSERT(HeapObjectHeader::fromPayload(m_raw)->checkHeader()); 828 m_gcGeneration = header->gcGeneration();
829 ASSERT(m_gcGeneration != gcGenerationForFreeListEntry);
830 }
810 #endif 831 #endif
811 } 832 }
812 833
813 T* m_raw; 834 T* m_raw;
814 835
836 #if ENABLE(ASSERT) && defined(ADDRESS_SANITIZER)
837 uint32_t m_gcGeneration;
838 #endif
839
815 template<bool x, WTF::WeakHandlingFlag y, WTF::ShouldWeakPointersBeMarkedStr ongly z, typename U, typename V> friend struct CollectionBackingTraceTrait; 840 template<bool x, WTF::WeakHandlingFlag y, WTF::ShouldWeakPointersBeMarkedStr ongly z, typename U, typename V> friend struct CollectionBackingTraceTrait;
816 friend class Visitor; 841 friend class Visitor;
817
818 }; 842 };
819 843
820 // WeakMember is similar to Member in that it is used to point to other oilpan 844 // WeakMember is similar to Member in that it is used to point to other oilpan
821 // heap allocated objects. 845 // heap allocated objects.
822 // However instead of creating a strong pointer to the object, the WeakMember cr eates 846 // However instead of creating a strong pointer to the object, the WeakMember cr eates
823 // a weak pointer, which does not keep the pointee alive. Hence if all pointers to 847 // a weak pointer, which does not keep the pointee alive. Hence if all pointers to
824 // to a heap allocated object are weak the object will be garbage collected. At the 848 // to a heap allocated object are weak the object will be garbage collected. At the
825 // time of GC the weak pointers will automatically be set to null. 849 // time of GC the weak pointers will automatically be set to null.
826 template<typename T> 850 template<typename T>
827 class WeakMember : public Member<T> { 851 class WeakMember : public Member<T> {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
871 this->checkPointer(); 895 this->checkPointer();
872 return *this; 896 return *this;
873 } 897 }
874 898
875 WeakMember& operator=(std::nullptr_t) 899 WeakMember& operator=(std::nullptr_t)
876 { 900 {
877 this->m_raw = nullptr; 901 this->m_raw = nullptr;
878 return *this; 902 return *this;
879 } 903 }
880 904
905 // TODO(peria): Remove this get() and use unsafeGet() at only
906 // where it is required.
907 T* get() const
908 {
909 // WeakMember may point to a dead object, so we skip the verification.
910 return Member<T>::unsafeGet();
911 }
912
881 private: 913 private:
882 T** cell() const { return const_cast<T**>(&this->m_raw); } 914 T** cell() const { return const_cast<T**>(&this->m_raw); }
883 915
884 template<typename Derived> friend class VisitorHelper; 916 template<typename Derived> friend class VisitorHelper;
885 }; 917 };
886 918
887 // UntracedMember is a pointer to an on-heap object that is not traced for some 919 // UntracedMember is a pointer to an on-heap object that is not traced for some
888 // reason. Please don't use this unless you understand what you're doing. 920 // reason. Please don't use this unless you understand what you're doing.
889 // Basically, all pointers to on-heap objects must be stored in either of 921 // Basically, all pointers to on-heap objects must be stored in either of
890 // Persistent, Member or WeakMember. It is not allowed to leave raw pointers to 922 // 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
945 } 977 }
946 978
947 UntracedMember& operator=(std::nullptr_t) 979 UntracedMember& operator=(std::nullptr_t)
948 { 980 {
949 this->m_raw = nullptr; 981 this->m_raw = nullptr;
950 return *this; 982 return *this;
951 } 983 }
952 }; 984 };
953 985
954 // Comparison operators between (Weak)Members, Persistents, and UntracedMembers. 986 // Comparison operators between (Weak)Members, Persistents, and UntracedMembers.
955 template<typename T, typename U> inline bool operator==(const Member<T>& a, cons t Member<U>& b) { return a.get() == b.get(); } 987 template<typename T, typename U> inline bool operator==(const Member<T>& a, cons t Member<U>& b) { return a.unsafeGet() == b.unsafeGet(); }
956 template<typename T, typename U> inline bool operator!=(const Member<T>& a, cons t Member<U>& b) { return a.get() != b.get(); } 988 template<typename T, typename U> inline bool operator!=(const Member<T>& a, cons t Member<U>& b) { return a.unsafeGet() != b.unsafeGet(); }
957 template<typename T, typename U> inline bool operator==(const Persistent<T>& a, const Persistent<U>& b) { return a.get() == b.get(); } 989 template<typename T, typename U> inline bool operator==(const Persistent<T>& a, const Persistent<U>& b) { return a.get() == b.get(); }
958 template<typename T, typename U> inline bool operator!=(const Persistent<T>& a, const Persistent<U>& b) { return a.get() != b.get(); } 990 template<typename T, typename U> inline bool operator!=(const Persistent<T>& a, const Persistent<U>& b) { return a.get() != b.get(); }
959 991
960 template<typename T, typename U> inline bool operator==(const Member<T>& a, cons t Persistent<U>& b) { return a.get() == b.get(); } 992 template<typename T, typename U> inline bool operator==(const Member<T>& a, cons t Persistent<U>& b) { return a.unsafeGet() == b.get(); }
961 template<typename T, typename U> inline bool operator!=(const Member<T>& a, cons t Persistent<U>& b) { return a.get() != b.get(); } 993 template<typename T, typename U> inline bool operator!=(const Member<T>& a, cons t Persistent<U>& b) { return a.unsafeGet() != b.get(); }
962 template<typename T, typename U> inline bool operator==(const Persistent<T>& a, const Member<U>& b) { return a.get() == b.get(); } 994 template<typename T, typename U> inline bool operator==(const Persistent<T>& a, const Member<U>& b) { return a.get() == b.unsafeGet(); }
963 template<typename T, typename U> inline bool operator!=(const Persistent<T>& a, const Member<U>& b) { return a.get() != b.get(); } 995 template<typename T, typename U> inline bool operator!=(const Persistent<T>& a, const Member<U>& b) { return a.get() != b.unsafeGet(); }
964 996
965 template<typename T> 997 template<typename T>
966 class DummyBase { 998 class DummyBase {
967 public: 999 public:
968 DummyBase() { } 1000 DummyBase() { }
969 ~DummyBase() { } 1001 ~DummyBase() { }
970 }; 1002 };
971 1003
972 // We need this explicit instantiation for component build on Windows. 1004 // We need this explicit instantiation for component build on Windows.
973 template<> 1005 template<>
(...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after
1413 1445
1414 template<typename T> struct PtrHash<blink::Member<T>> : PtrHash<T*> { 1446 template<typename T> struct PtrHash<blink::Member<T>> : PtrHash<T*> {
1415 template<typename U> 1447 template<typename U>
1416 static unsigned hash(const U& key) { return PtrHash<T*>::hash(key); } 1448 static unsigned hash(const U& key) { return PtrHash<T*>::hash(key); }
1417 static bool equal(T* a, const blink::Member<T>& b) { return a == b; } 1449 static bool equal(T* a, const blink::Member<T>& b) { return a == b; }
1418 static bool equal(const blink::Member<T>& a, T* b) { return a == b; } 1450 static bool equal(const blink::Member<T>& a, T* b) { return a == b; }
1419 template<typename U, typename V> 1451 template<typename U, typename V>
1420 static bool equal(const U& a, const V& b) { return a == b; } 1452 static bool equal(const U& a, const V& b) { return a == b; }
1421 }; 1453 };
1422 1454
1423 template<typename T> struct PtrHash<blink::WeakMember<T>> : PtrHash<blink::Membe r<T>> { 1455 template<typename T> struct PtrHash<blink::WeakMember<T>> : PtrHash<blink::Membe r<T>> { };
1424 };
1425 1456
1426 template<typename T> struct PtrHash<blink::UntracedMember<T>> : PtrHash<blink::M ember<T>> { 1457 template<typename T> struct PtrHash<blink::UntracedMember<T>> : PtrHash<blink::M ember<T>> { };
1427 };
1428 1458
1429 // PtrHash is the default hash for hash tables with members. 1459 // PtrHash is the default hash for hash tables with members.
1430 template<typename T> struct DefaultHash<blink::Member<T>> { 1460 template<typename T> struct DefaultHash<blink::Member<T>> {
1431 using Hash = PtrHash<blink::Member<T>>; 1461 using Hash = PtrHash<blink::Member<T>>;
1432 }; 1462 };
1433 1463
1434 template<typename T> struct DefaultHash<blink::WeakMember<T>> { 1464 template<typename T> struct DefaultHash<blink::WeakMember<T>> {
1435 using Hash = PtrHash<blink::WeakMember<T>>; 1465 using Hash = PtrHash<blink::WeakMember<T>>;
1436 }; 1466 };
1437 1467
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
1510 // TODO(sof): extend WTF::FunctionWrapper call overloading to also handle (C rossThread)WeakPersistent. 1540 // TODO(sof): extend WTF::FunctionWrapper call overloading to also handle (C rossThread)WeakPersistent.
1511 static T* unwrap(const StorageType& value) { return value.get(); } 1541 static T* unwrap(const StorageType& value) { return value.get(); }
1512 }; 1542 };
1513 1543
1514 template<typename T> 1544 template<typename T>
1515 PassRefPtr<T> adoptRef(blink::RefCountedGarbageCollected<T>*) = delete; 1545 PassRefPtr<T> adoptRef(blink::RefCountedGarbageCollected<T>*) = delete;
1516 1546
1517 } // namespace WTF 1547 } // namespace WTF
1518 1548
1519 #endif 1549 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698