summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorKostya Serebryany <kcc@google.com>2012-12-19 08:32:50 +0000
committerKostya Serebryany <kcc@google.com>2012-12-19 08:32:50 +0000
commit2592d766401edb3d36676f1f522592f1d5fb2b07 (patch)
tree6fb05c9ca6506f5f2142bf938196f72b56dfff8a /lib
parent2bac661ab19b8657f42c5bc4f2abd03dd75e51c2 (diff)
downloadcompiler-rt-2592d766401edb3d36676f1f522592f1d5fb2b07.tar.gz
compiler-rt-2592d766401edb3d36676f1f522592f1d5fb2b07.tar.bz2
compiler-rt-2592d766401edb3d36676f1f522592f1d5fb2b07.tar.xz
[asan] asan_allocator2: improve FindHeapChunkByAddress to find memory chunks to the left of a given address. Almost all tests pass with the new allocator now, only 6 are left to fix.
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@170511 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/asan/asan_allocator2.cc40
-rw-r--r--lib/sanitizer_common/sanitizer_allocator.h7
2 files changed, 43 insertions, 4 deletions
diff --git a/lib/asan/asan_allocator2.cc b/lib/asan/asan_allocator2.cc
index 8153a1d7..5dac6654 100644
--- a/lib/asan/asan_allocator2.cc
+++ b/lib/asan/asan_allocator2.cc
@@ -378,8 +378,44 @@ static uptr AllocationSize(uptr p) {
return m->UsedSize();
}
-AsanChunkView FindHeapChunkByAddress(uptr address) {
- return AsanChunkView(GetAsanChunkByAddr(address));
+// We have an address between two chunks, and we want to report just one.
+AsanChunk *ChooseChunk(uptr addr,
+ AsanChunk *left_chunk, AsanChunk *right_chunk) {
+ // Prefer an allocated chunk or a chunk from quarantine.
+ if (left_chunk->chunk_state == CHUNK_AVAILABLE &&
+ right_chunk->chunk_state != CHUNK_AVAILABLE)
+ return right_chunk;
+ if (right_chunk->chunk_state == CHUNK_AVAILABLE &&
+ left_chunk->chunk_state != CHUNK_AVAILABLE)
+ return left_chunk;
+ // Choose based on offset.
+ uptr l_offset = 0, r_offset = 0;
+ CHECK(AsanChunkView(left_chunk).AddrIsAtRight(addr, 1, &l_offset));
+ CHECK(AsanChunkView(right_chunk).AddrIsAtLeft(addr, 1, &r_offset));
+ if (l_offset < r_offset)
+ return left_chunk;
+ return right_chunk;
+}
+
+AsanChunkView FindHeapChunkByAddress(uptr addr) {
+ AsanChunk *m1 = GetAsanChunkByAddr(addr);
+ if (!m1) return AsanChunkView(m1);
+ uptr offset = 0;
+ if (AsanChunkView(m1).AddrIsAtLeft(addr, 1, &offset)) {
+ // The address is in the chunk's left redzone, so maybe it is actually
+ // a right buffer overflow from the other chunk to the left.
+ // Search a bit to the left to see if there is another chunk.
+ AsanChunk *m2 = 0;
+ for (uptr l = 1; l < GetPageSizeCached(); l++) {
+ m2 = GetAsanChunkByAddr(addr - l);
+ if (m2 == m1) continue; // Still the same chunk.
+ Printf("m1 %p m2 %p l %zd\n", m1, m2, l);
+ break;
+ }
+ if (m2 && AsanChunkView(m2).AddrIsAtRight(addr, 1, &offset))
+ m1 = ChooseChunk(addr, m2, m1);
+ }
+ return AsanChunkView(m1);
}
void AsanThreadLocalMallocStorage::CommitBack() {
diff --git a/lib/sanitizer_common/sanitizer_allocator.h b/lib/sanitizer_common/sanitizer_allocator.h
index 87a7fc1a..5376875a 100644
--- a/lib/sanitizer_common/sanitizer_allocator.h
+++ b/lib/sanitizer_common/sanitizer_allocator.h
@@ -207,13 +207,16 @@ class SizeClassAllocator64 {
return (reinterpret_cast<uptr>(p) / kRegionSize) % kNumClasses;
}
- static void *GetBlockBegin(void *p) {
+ void *GetBlockBegin(void *p) {
uptr class_id = GetSizeClass(p);
uptr size = SizeClassMap::Size(class_id);
uptr chunk_idx = GetChunkIdx((uptr)p, size);
uptr reg_beg = (uptr)p & ~(kRegionSize - 1);
uptr begin = reg_beg + chunk_idx * size;
- return reinterpret_cast<void*>(begin);
+ RegionInfo *region = GetRegionInfo(class_id);
+ if (region->allocated_user >= (chunk_idx + 1) * size)
+ return reinterpret_cast<void*>(begin);
+ return 0;
}
static uptr GetActuallyAllocatedSize(void *p) {