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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/platform/heap/Handle.h
diff --git a/third_party/WebKit/Source/platform/heap/Handle.h b/third_party/WebKit/Source/platform/heap/Handle.h
index b5e0eb399a1ed538ee1418d8a14089c51250026a..5ad7a6cb8ce2fffa534a2ccad7d21f57b0ab781a 100644
--- a/third_party/WebKit/Source/platform/heap/Handle.h
+++ b/third_party/WebKit/Source/platform/heap/Handle.h
@@ -656,6 +656,36 @@ public:
}
};
+template<typename T, bool = IsGarbageCollectedMixin<T>::value> class GarbageCollectedMixinTrait;
+template<typename T>
+class GarbageCollectedMixinTrait<T, true> {
+public:
+ static HeapObjectHeader* heapObjectHeader(T* obj)
+ {
+ return obj->heapObjectHeader();
+ }
+ static uint16_t gcGeneration(T* obj)
+ {
+ // While constructing GarbageCollectedMixin classes, we skip looking
+ // 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.
+ 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
+ return 0;
+ return heapObjectHeader(obj)->gcGeneration();
+ }
+};
+template<typename T>
+class GarbageCollectedMixinTrait<T, false> {
+public:
+ static HeapObjectHeader* heapObjectHeader(T* obj)
+ {
+ return HeapObjectHeader::fromPayload(obj);
+ }
+ static uint16_t gcGeneration(T* obj)
+ {
+ return heapObjectHeader(obj)->gcGeneration();
+ }
+};
+
// Members are used in classes to contain strong pointers to other oilpan heap
// allocated objects.
// All Member fields of a class must be traced in the class' trace method.
@@ -666,10 +696,12 @@ class Member {
public:
Member() : m_raw(nullptr)
{
+ checkPointer();
}
Member(std::nullptr_t) : m_raw(nullptr)
{
+ checkPointer();
}
Member(T* raw) : m_raw(raw)
@@ -762,6 +794,7 @@ public:
Member& operator=(std::nullptr_t)
{
m_raw = nullptr;
+ checkPointer();
return *this;
}
@@ -771,17 +804,40 @@ public:
checkPointer();
}
- T* get() const { return m_raw; }
+ T* get() const
+ {
+#if ENABLE(ASSERT)
+ // 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.
+ // has been assigned to this handle out of GarbageCollectedMixin constructions.
+ if (m_raw && m_gcGeneration) {
+ ASSERT(m_gcGeneration == GarbageCollectedMixinTrait<T>::heapObjectHeader(m_raw)->gcGeneration());
+ }
+#endif
+ return m_raw;
+ }
- void clear() { m_raw = nullptr; }
+ // This method is an accessor without any security checks, and it is
+ // expected to be used under some limited condition.
+ // So do NOT use it, if you do not know what it means.
+ T* unsafeGet() const
+ {
+ return m_raw;
+ }
+ void clear()
+ {
+ m_raw = nullptr;
+ checkPointer();
+ }
protected:
void checkPointer()
{
#if ENABLE(ASSERT)
- if (!m_raw)
+ if (!m_raw) {
+ 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.
return;
+ }
// HashTable can store a special value (which is not aligned to the
// allocation granularity) to Member<> to represent a deleted entry.
// Thus we treat a pointer that is not aligned to the granularity
@@ -799,16 +855,18 @@ protected:
// but we cannot call it here because it requires to include T.h.
// So we currently only try to implement the check for (a), but do
// not insist that T's definition is in scope.
- if (IsFullyDefined<T>::value && !IsGarbageCollectedMixin<T>::value)
- ASSERT(HeapObjectHeader::fromPayload(m_raw)->checkHeader());
+ 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.
#endif
}
T* m_raw;
+#if ENABLE(ASSERT)
+ uint16_t m_gcGeneration;
+#endif
+
template<bool x, WTF::WeakHandlingFlag y, WTF::ShouldWeakPointersBeMarkedStrongly z, typename U, typename V> friend struct CollectionBackingTraceTrait;
friend class Visitor;
-
};
// WeakMember is similar to Member in that it is used to point to other oilpan
@@ -869,6 +927,7 @@ public:
WeakMember& operator=(std::nullptr_t)
{
this->m_raw = nullptr;
+ this->checkPointer();
return *this;
}
@@ -941,13 +1000,14 @@ public:
UntracedMember& operator=(std::nullptr_t)
{
this->m_raw = nullptr;
+ this->checkPointer();
return *this;
}
};
// Comparison operators between (Weak)Members, Persistents, and UntracedMembers.
-template<typename T, typename U> inline bool operator==(const Member<T>& a, const Member<U>& b) { return a.get() == b.get(); }
-template<typename T, typename U> inline bool operator!=(const Member<T>& a, const Member<U>& b) { return a.get() != b.get(); }
+template<typename T, typename U> inline bool operator==(const Member<T>& a, const Member<U>& b) { return a.unsafeGet() == b.unsafeGet(); }
+template<typename T, typename U> inline bool operator!=(const Member<T>& a, const Member<U>& b) { return a.unsafeGet() != b.unsafeGet(); }
template<typename T, typename U> inline bool operator==(const Persistent<T>& a, const Persistent<U>& b) { return a.get() == b.get(); }
template<typename T, typename U> inline bool operator!=(const Persistent<T>& a, const Persistent<U>& b) { return a.get() != b.get(); }
@@ -1414,11 +1474,9 @@ template<typename T> struct PtrHash<blink::Member<T>> : PtrHash<T*> {
static bool equal(const U& a, const V& b) { return a == b; }
};
-template<typename T> struct PtrHash<blink::WeakMember<T>> : PtrHash<blink::Member<T>> {
-};
+template<typename T> struct PtrHash<blink::WeakMember<T>> : PtrHash<blink::Member<T>> { };
-template<typename T> struct PtrHash<blink::UntracedMember<T>> : PtrHash<blink::Member<T>> {
-};
+template<typename T> struct PtrHash<blink::UntracedMember<T>> : PtrHash<blink::Member<T>> { };
// PtrHash is the default hash for hash tables with members.
template<typename T> struct DefaultHash<blink::Member<T>> {

Powered by Google App Engine
This is Rietveld 408576698