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

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: 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 GarbageColl ectedMixinTrait;
660 template<typename T>
661 class GarbageCollectedMixinTrait<T, true> {
662 public:
663 static HeapObjectHeader* heapObjectHeader(T* obj)
664 {
665 return obj->heapObjectHeader();
666 }
667 static uint16_t gcGeneration(T* obj)
668 {
669 // While constructing GarbageCollectedMixin classes, we skip looking
670 // for gcGeneration, because the object may not be fully allocated.
haraken 2015/11/10 16:37:05 Sorry, I'm getting confused. Why can't we call hea
peria 2015/11/11 02:46:34 obj->heapObjectHeader() (on line#665) depends on t
haraken 2015/11/11 04:19:29 Thanks for the clarification; now I understand the
peria 2015/11/11 05:51:51 SGTM I moved this Trait to Heap.h in PS6.
671 if (ThreadState::current()->isGCForbidden())
haraken 2015/11/10 16:37:05 Let's rename isGCForbidden() to isConstructingGCMi
peria 2015/11/11 05:51:51 Renaming it looks confusing in other places, so I
672 return 0;
673 return heapObjectHeader(obj)->gcGeneration();
674 }
675 };
676 template<typename T>
677 class GarbageCollectedMixinTrait<T, false> {
678 public:
679 static HeapObjectHeader* heapObjectHeader(T* obj)
680 {
681 return HeapObjectHeader::fromPayload(obj);
682 }
683 static uint16_t gcGeneration(T* obj)
684 {
685 return heapObjectHeader(obj)->gcGeneration();
686 }
687 };
688
659 // Members are used in classes to contain strong pointers to other oilpan heap 689 // Members are used in classes to contain strong pointers to other oilpan heap
660 // allocated objects. 690 // allocated objects.
661 // All Member fields of a class must be traced in the class' trace method. 691 // 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 692 // 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. 693 // all Member fields of a live object will be traced marked as live as well.
664 template<typename T> 694 template<typename T>
665 class Member { 695 class Member {
666 public: 696 public:
667 Member() : m_raw(nullptr) 697 Member() : m_raw(nullptr)
668 { 698 {
699 checkPointer();
669 } 700 }
670 701
671 Member(std::nullptr_t) : m_raw(nullptr) 702 Member(std::nullptr_t) : m_raw(nullptr)
672 { 703 {
704 checkPointer();
673 } 705 }
674 706
675 Member(T* raw) : m_raw(raw) 707 Member(T* raw) : m_raw(raw)
676 { 708 {
677 checkPointer(); 709 checkPointer();
678 } 710 }
679 711
680 explicit Member(T& raw) : m_raw(&raw) 712 explicit Member(T& raw) : m_raw(&raw)
681 { 713 {
682 checkPointer(); 714 checkPointer();
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
755 Member& operator=(RawPtr<U> other) 787 Member& operator=(RawPtr<U> other)
756 { 788 {
757 m_raw = other; 789 m_raw = other;
758 checkPointer(); 790 checkPointer();
759 return *this; 791 return *this;
760 } 792 }
761 793
762 Member& operator=(std::nullptr_t) 794 Member& operator=(std::nullptr_t)
763 { 795 {
764 m_raw = nullptr; 796 m_raw = nullptr;
797 checkPointer();
765 return *this; 798 return *this;
766 } 799 }
767 800
768 void swap(Member<T>& other) 801 void swap(Member<T>& other)
769 { 802 {
770 std::swap(m_raw, other.m_raw); 803 std::swap(m_raw, other.m_raw);
771 checkPointer(); 804 checkPointer();
772 } 805 }
773 806
774 T* get() const { return m_raw; } 807 T* get() const
808 {
809 #if ENABLE(ASSERT)
810 // Verify that this handle points a live on-heap object, if a pointer
haraken 2015/11/10 16:37:05 points to
peria 2015/11/11 02:46:34 Done.
811 // has been assigned to this handle out of GarbageCollectedMixin constru ctions.
812 if (m_raw && m_gcGeneration) {
813 ASSERT(m_gcGeneration == GarbageCollectedMixinTrait<T>::heapObjectHe ader(m_raw)->gcGeneration());
814 }
815 #endif
816 return m_raw;
817 }
775 818
776 void clear() { m_raw = nullptr; } 819 // This method is an accessor without any security checks, and it is
820 // expected to be used under some limited condition.
821 // So do NOT use it, if you do not know what it means.
822 T* unsafeGet() const
823 {
824 return m_raw;
825 }
777 826
827 void clear()
828 {
829 m_raw = nullptr;
830 checkPointer();
831 }
778 832
779 protected: 833 protected:
780 void checkPointer() 834 void checkPointer()
781 { 835 {
782 #if ENABLE(ASSERT) 836 #if ENABLE(ASSERT)
783 if (!m_raw) 837 if (!m_raw) {
838 m_gcGeneration = 0;
haraken 2015/11/10 16:37:05 You won't need this. Given that you're checking if
peria 2015/11/11 02:46:34 Agree. Done.
784 return; 839 return;
840 }
785 // HashTable can store a special value (which is not aligned to the 841 // HashTable can store a special value (which is not aligned to the
786 // allocation granularity) to Member<> to represent a deleted entry. 842 // allocation granularity) to Member<> to represent a deleted entry.
787 // Thus we treat a pointer that is not aligned to the granularity 843 // Thus we treat a pointer that is not aligned to the granularity
788 // as a valid pointer. 844 // as a valid pointer.
789 if (reinterpret_cast<intptr_t>(m_raw) % allocationGranularity) 845 if (reinterpret_cast<intptr_t>(m_raw) % allocationGranularity)
790 return; 846 return;
791 847
792 // TODO(haraken): What we really want to check here is that the pointer 848 // 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: 849 // is a traceable object. In other words, the pointer is either of:
794 // 850 //
795 // (a) a pointer to the head of an on-heap object. 851 // (a) a pointer to the head of an on-heap object.
796 // (b) a pointer to the head of an on-heap mixin object. 852 // (b) a pointer to the head of an on-heap mixin object.
797 // 853 //
798 // We can check it by calling Heap::isHeapObjectAlive(m_raw), 854 // We can check it by calling Heap::isHeapObjectAlive(m_raw),
799 // but we cannot call it here because it requires to include T.h. 855 // 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 856 // So we currently only try to implement the check for (a), but do
801 // not insist that T's definition is in scope. 857 // not insist that T's definition is in scope.
802 if (IsFullyDefined<T>::value && !IsGarbageCollectedMixin<T>::value) 858 m_gcGeneration = GarbageCollectedMixinTrait<T>::gcGeneration(m_raw);
haraken 2015/11/11 04:19:29 So you can update the code to: HeapObjectHeader
peria 2015/11/11 05:51:51 Acknowledged.
803 ASSERT(HeapObjectHeader::fromPayload(m_raw)->checkHeader());
804 #endif 859 #endif
805 } 860 }
806 861
807 T* m_raw; 862 T* m_raw;
808 863
864 #if ENABLE(ASSERT)
865 uint16_t m_gcGeneration;
866 #endif
867
809 template<bool x, WTF::WeakHandlingFlag y, WTF::ShouldWeakPointersBeMarkedStr ongly z, typename U, typename V> friend struct CollectionBackingTraceTrait; 868 template<bool x, WTF::WeakHandlingFlag y, WTF::ShouldWeakPointersBeMarkedStr ongly z, typename U, typename V> friend struct CollectionBackingTraceTrait;
810 friend class Visitor; 869 friend class Visitor;
811
812 }; 870 };
813 871
814 // WeakMember is similar to Member in that it is used to point to other oilpan 872 // WeakMember is similar to Member in that it is used to point to other oilpan
815 // heap allocated objects. 873 // heap allocated objects.
816 // However instead of creating a strong pointer to the object, the WeakMember cr eates 874 // 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 875 // 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 876 // 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. 877 // time of GC the weak pointers will automatically be set to null.
820 template<typename T> 878 template<typename T>
821 class WeakMember : public Member<T> { 879 class WeakMember : public Member<T> {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
862 WeakMember& operator=(const RawPtr<U>& other) 920 WeakMember& operator=(const RawPtr<U>& other)
863 { 921 {
864 this->m_raw = other; 922 this->m_raw = other;
865 this->checkPointer(); 923 this->checkPointer();
866 return *this; 924 return *this;
867 } 925 }
868 926
869 WeakMember& operator=(std::nullptr_t) 927 WeakMember& operator=(std::nullptr_t)
870 { 928 {
871 this->m_raw = nullptr; 929 this->m_raw = nullptr;
930 this->checkPointer();
872 return *this; 931 return *this;
873 } 932 }
874 933
875 private: 934 private:
876 T** cell() const { return const_cast<T**>(&this->m_raw); } 935 T** cell() const { return const_cast<T**>(&this->m_raw); }
877 936
878 template<typename Derived> friend class VisitorHelper; 937 template<typename Derived> friend class VisitorHelper;
879 }; 938 };
880 939
881 // UntracedMember is a pointer to an on-heap object that is not traced for some 940 // 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) 993 UntracedMember& operator=(const RawPtr<U>& other)
935 { 994 {
936 this->m_raw = other; 995 this->m_raw = other;
937 this->checkPointer(); 996 this->checkPointer();
938 return *this; 997 return *this;
939 } 998 }
940 999
941 UntracedMember& operator=(std::nullptr_t) 1000 UntracedMember& operator=(std::nullptr_t)
942 { 1001 {
943 this->m_raw = nullptr; 1002 this->m_raw = nullptr;
1003 this->checkPointer();
944 return *this; 1004 return *this;
945 } 1005 }
946 }; 1006 };
947 1007
948 // Comparison operators between (Weak)Members, Persistents, and UntracedMembers. 1008 // 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(); } 1009 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(); } 1010 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(); } 1011 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(); } 1012 template<typename T, typename U> inline bool operator!=(const Persistent<T>& a, const Persistent<U>& b) { return a.get() != b.get(); }
953 1013
954 template<typename T, typename U> inline bool operator==(const Member<T>& a, cons t Persistent<U>& b) { return a.get() == b.get(); } 1014 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(); } 1015 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(); } 1016 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(); } 1017 template<typename T, typename U> inline bool operator!=(const Persistent<T>& a, const Member<U>& b) { return a.get() != b.get(); }
958 1018
959 template<typename T> 1019 template<typename T>
960 class DummyBase { 1020 class DummyBase {
(...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after
1407 1467
1408 template<typename T> struct PtrHash<blink::Member<T>> : PtrHash<T*> { 1468 template<typename T> struct PtrHash<blink::Member<T>> : PtrHash<T*> {
1409 template<typename U> 1469 template<typename U>
1410 static unsigned hash(const U& key) { return PtrHash<T*>::hash(key); } 1470 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; } 1471 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; } 1472 static bool equal(const blink::Member<T>& a, T* b) { return a == b; }
1413 template<typename U, typename V> 1473 template<typename U, typename V>
1414 static bool equal(const U& a, const V& b) { return a == b; } 1474 static bool equal(const U& a, const V& b) { return a == b; }
1415 }; 1475 };
1416 1476
1417 template<typename T> struct PtrHash<blink::WeakMember<T>> : PtrHash<blink::Membe r<T>> { 1477 template<typename T> struct PtrHash<blink::WeakMember<T>> : PtrHash<blink::Membe r<T>> { };
1418 };
1419 1478
1420 template<typename T> struct PtrHash<blink::UntracedMember<T>> : PtrHash<blink::M ember<T>> { 1479 template<typename T> struct PtrHash<blink::UntracedMember<T>> : PtrHash<blink::M ember<T>> { };
1421 };
1422 1480
1423 // PtrHash is the default hash for hash tables with members. 1481 // PtrHash is the default hash for hash tables with members.
1424 template<typename T> struct DefaultHash<blink::Member<T>> { 1482 template<typename T> struct DefaultHash<blink::Member<T>> {
1425 using Hash = PtrHash<blink::Member<T>>; 1483 using Hash = PtrHash<blink::Member<T>>;
1426 }; 1484 };
1427 1485
1428 template<typename T> struct DefaultHash<blink::WeakMember<T>> { 1486 template<typename T> struct DefaultHash<blink::WeakMember<T>> {
1429 using Hash = PtrHash<blink::WeakMember<T>>; 1487 using Hash = PtrHash<blink::WeakMember<T>>;
1430 }; 1488 };
1431 1489
(...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. 1562 // TODO(sof): extend WTF::FunctionWrapper call overloading to also handle (C rossThread)WeakPersistent.
1505 static T* unwrap(const StorageType& value) { return value.get(); } 1563 static T* unwrap(const StorageType& value) { return value.get(); }
1506 }; 1564 };
1507 1565
1508 template<typename T> 1566 template<typename T>
1509 PassRefPtr<T> adoptRef(blink::RefCountedGarbageCollected<T>*) = delete; 1567 PassRefPtr<T> adoptRef(blink::RefCountedGarbageCollected<T>*) = delete;
1510 1568
1511 } // namespace WTF 1569 } // namespace WTF
1512 1570
1513 #endif 1571 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698