Index: Source/platform/heap/Heap.cpp |
diff --git a/Source/platform/heap/Heap.cpp b/Source/platform/heap/Heap.cpp |
index c3c3eaddbfea5bb8fecfd098a1bce0840bbdaae0..22469cb42314e4176d1df963e4ad80ebde5b757a 100644 |
--- a/Source/platform/heap/Heap.cpp |
+++ b/Source/platform/heap/Heap.cpp |
@@ -583,6 +583,17 @@ void BaseHeap::prepareForSweep() |
m_firstPage = nullptr; |
} |
+#if defined(ADDRESS_SANITIZER) |
+void BaseHeap::poisonUnmarkedObjects() |
+{ |
+ // This method is called just before starting sweeping. |
+ // Thus all dead objects are in the list of m_firstUnsweptPage. |
+ for (BasePage* page = m_firstUnsweptPage; page; page = page->next()) { |
+ page->poisonUnmarkedObjects(); |
+ } |
+} |
+#endif |
+ |
Address BaseHeap::lazySweep(size_t allocationSize, size_t gcInfoIndex) |
{ |
// If there are no pages to be swept, return immediately. |
@@ -1506,8 +1517,9 @@ void NormalPage::sweep() |
Address payload = header->payload(); |
// For ASan we unpoison the specific object when calling the |
// finalizer and poison it again when done to allow the object's own |
- // finalizer to operate on the object, but not have other finalizers |
- // be allowed to access it. |
+ // finalizer to operate on the object. Given all other unmarked |
+ // objects are poisoned, ASan will detect an error if the finalizer |
+ // touches any other on-heap object that die at the same GC cycle. |
ASAN_UNPOISON_MEMORY_REGION(payload, payloadSize); |
header->finalize(payload, payloadSize); |
// This memory will be added to the freelist. Maintain the invariant |
@@ -1557,6 +1569,27 @@ void NormalPage::markUnmarkedObjectsDead() |
Heap::increaseMarkedObjectSize(markedObjectSize); |
} |
+#if defined(ADDRESS_SANITIZER) |
+void NormalPage::poisonUnmarkedObjects() |
+{ |
+ for (Address headerAddress = payload(); headerAddress < payloadEnd();) { |
+ HeapObjectHeader* header = reinterpret_cast<HeapObjectHeader*>(headerAddress); |
+ ASSERT(header->size() < blinkPagePayloadSize()); |
+ // Check if a free list entry first since we cannot call |
+ // isMarked on a free list entry. |
+ if (header->isFree()) { |
+ headerAddress += header->size(); |
+ continue; |
+ } |
+ header->checkHeader(); |
+ if (!header->isMarked()) { |
+ ASAN_POISON_MEMORY_REGION(header->payload(), header->payloadSize()); |
+ } |
+ headerAddress += header->size(); |
+ } |
+} |
+#endif |
+ |
void NormalPage::populateObjectStartBitMap() |
{ |
memset(&m_objectStartBitMap, 0, objectStartBitMapSize); |
@@ -1823,6 +1856,15 @@ void LargeObjectPage::markUnmarkedObjectsDead() |
} |
} |
+#if defined(ADDRESS_SANITIZER) |
+void LargeObjectPage::poisonUnmarkedObjects() |
+{ |
+ HeapObjectHeader* header = heapObjectHeader(); |
+ if (!header->isMarked()) |
+ ASAN_POISON_MEMORY_REGION(header->payload(), header->payloadSize()); |
+} |
+#endif |
+ |
void LargeObjectPage::checkAndMarkPointer(Visitor* visitor, Address address) |
{ |
ASSERT(contains(address)); |