diff options
author | Kostya Serebryany <kcc@google.com> | 2012-12-19 08:32:50 +0000 |
---|---|---|
committer | Kostya Serebryany <kcc@google.com> | 2012-12-19 08:32:50 +0000 |
commit | 2592d766401edb3d36676f1f522592f1d5fb2b07 (patch) | |
tree | 6fb05c9ca6506f5f2142bf938196f72b56dfff8a /lib | |
parent | 2bac661ab19b8657f42c5bc4f2abd03dd75e51c2 (diff) | |
download | compiler-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.cc | 40 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_allocator.h | 7 |
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) { |