186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines//===-- asan_allocator.cc -------------------------------------------------===// 286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// 386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// The LLVM Compiler Infrastructure 486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// 586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// This file is distributed under the University of Illinois Open Source 686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// License. See LICENSE.TXT for details. 786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// 886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines//===----------------------------------------------------------------------===// 986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// 1086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// This file is a part of AddressSanitizer, an address sanity checker. 1186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// 1286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// Implementation of ASan's memory allocator, 2-nd version. 1386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// This variant uses the allocator from sanitizer_common, i.e. the one shared 1486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// with ThreadSanitizer and MemorySanitizer. 1586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// 1686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines//===----------------------------------------------------------------------===// 1786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 183d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar#include "asan_allocator.h" 1986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include "asan_mapping.h" 2086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include "asan_poisoning.h" 2186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include "asan_report.h" 2286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include "asan_stack.h" 2386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include "asan_thread.h" 2486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include "sanitizer_common/sanitizer_allocator_interface.h" 2586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include "sanitizer_common/sanitizer_flags.h" 2686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include "sanitizer_common/sanitizer_internal_defs.h" 2786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include "sanitizer_common/sanitizer_list.h" 2886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include "sanitizer_common/sanitizer_stackdepot.h" 2986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include "sanitizer_common/sanitizer_quarantine.h" 3086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include "lsan/lsan_common.h" 3186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 3286277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesnamespace __asan { 3386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 3486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// Valid redzone sizes are 16, 32, 64, ... 2048, so we encode them in 3 bits. 3586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// We use adaptive redzones: for larger allocation larger redzones are used. 3686277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstatic u32 RZLog2Size(u32 rz_log) { 3786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CHECK_LT(rz_log, 8); 3886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return 16 << rz_log; 3986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 4086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 4186277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstatic u32 RZSize2Log(u32 rz_size) { 4286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CHECK_GE(rz_size, 16); 4386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CHECK_LE(rz_size, 2048); 4486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CHECK(IsPowerOfTwo(rz_size)); 4586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines u32 res = Log2(rz_size) - 4; 4686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CHECK_EQ(rz_size, RZLog2Size(res)); 4786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return res; 4886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 4986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 5086277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstatic AsanAllocator &get_allocator(); 5186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 5286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// The memory chunk allocated from the underlying allocator looks like this: 5386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// L L L L L L H H U U U U U U R R 5486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// L -- left redzone words (0 or more bytes) 5586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// H -- ChunkHeader (16 bytes), which is also a part of the left redzone. 5686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// U -- user memory. 5786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// R -- right redzone (0 or more bytes) 5886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// ChunkBase consists of ChunkHeader and other bytes that overlap with user 5986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// memory. 6086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 6186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// If the left redzone is greater than the ChunkHeader size we store a magic 6286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// value in the first uptr word of the memory block and store the address of 6386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// ChunkBase in the next uptr. 6486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// M B L L L L L L L L L H H U U U U U U 6586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// | ^ 6686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// ---------------------| 6786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// M -- magic value kAllocBegMagic 6886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// B -- address of ChunkHeader pointing to the first 'H' 6986277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstatic const uptr kAllocBegMagic = 0xCC6E96B9; 7086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 7186277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstruct ChunkHeader { 7286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // 1-st 8 bytes. 7386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines u32 chunk_state : 8; // Must be first. 7486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines u32 alloc_tid : 24; 7586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 7686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines u32 free_tid : 24; 7786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines u32 from_memalign : 1; 7886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines u32 alloc_type : 2; 7986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines u32 rz_log : 3; 8086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines u32 lsan_tag : 2; 8186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // 2-nd 8 bytes 8286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // This field is used for small sizes. For large sizes it is equal to 8386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // SizeClassMap::kMaxSize and the actual size is stored in the 8486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // SecondaryAllocator's metadata. 8586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines u32 user_requested_size; 8686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines u32 alloc_context_id; 8786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}; 8886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 8986277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstruct ChunkBase : ChunkHeader { 9086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // Header2, intersects with user memory. 9186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines u32 free_context_id; 9286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}; 9386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 9486277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstatic const uptr kChunkHeaderSize = sizeof(ChunkHeader); 9586277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstatic const uptr kChunkHeader2Size = sizeof(ChunkBase) - kChunkHeaderSize; 9686277eb844c4983c81de62d7c050e92fe7155788Stephen HinesCOMPILER_CHECK(kChunkHeaderSize == 16); 9786277eb844c4983c81de62d7c050e92fe7155788Stephen HinesCOMPILER_CHECK(kChunkHeader2Size <= 16); 9886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 9986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// Every chunk of memory allocated by this allocator can be in one of 3 states: 10086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// CHUNK_AVAILABLE: the chunk is in the free list and ready to be allocated. 10186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// CHUNK_ALLOCATED: the chunk is allocated and not yet freed. 10286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// CHUNK_QUARANTINE: the chunk was freed and put into quarantine zone. 10386277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesenum { 10486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CHUNK_AVAILABLE = 0, // 0 is the default value even if we didn't set it. 10586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CHUNK_ALLOCATED = 2, 10686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CHUNK_QUARANTINE = 3 10786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}; 10886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 10986277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstruct AsanChunk: ChunkBase { 11086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines uptr Beg() { return reinterpret_cast<uptr>(this) + kChunkHeaderSize; } 11186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines uptr UsedSize(bool locked_version = false) { 11286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (user_requested_size != SizeClassMap::kMaxSize) 11386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return user_requested_size; 11486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return *reinterpret_cast<uptr *>( 11586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines get_allocator().GetMetaData(AllocBeg(locked_version))); 11686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 11786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines void *AllocBeg(bool locked_version = false) { 11886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (from_memalign) { 11986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (locked_version) 12086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return get_allocator().GetBlockBeginFastLocked( 12186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines reinterpret_cast<void *>(this)); 12286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return get_allocator().GetBlockBegin(reinterpret_cast<void *>(this)); 12386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 12486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return reinterpret_cast<void*>(Beg() - RZLog2Size(rz_log)); 12586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 12686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines bool AddrIsInside(uptr addr, bool locked_version = false) { 12786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return (addr >= Beg()) && (addr < Beg() + UsedSize(locked_version)); 12886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 12986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}; 13086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 13186277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstruct QuarantineCallback { 13286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines explicit QuarantineCallback(AllocatorCache *cache) 13386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines : cache_(cache) { 13486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 13586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 13686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines void Recycle(AsanChunk *m) { 13786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CHECK_EQ(m->chunk_state, CHUNK_QUARANTINE); 13886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines atomic_store((atomic_uint8_t*)m, CHUNK_AVAILABLE, memory_order_relaxed); 13986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CHECK_NE(m->alloc_tid, kInvalidTid); 14086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CHECK_NE(m->free_tid, kInvalidTid); 14186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines PoisonShadow(m->Beg(), 14286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines RoundUpTo(m->UsedSize(), SHADOW_GRANULARITY), 14386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines kAsanHeapLeftRedzoneMagic); 14486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines void *p = reinterpret_cast<void *>(m->AllocBeg()); 14586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (p != m) { 14686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines uptr *alloc_magic = reinterpret_cast<uptr *>(p); 14786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CHECK_EQ(alloc_magic[0], kAllocBegMagic); 14886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // Clear the magic value, as allocator internals may overwrite the 14986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // contents of deallocated chunk, confusing GetAsanChunk lookup. 15086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines alloc_magic[0] = 0; 15186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CHECK_EQ(alloc_magic[1], reinterpret_cast<uptr>(m)); 15286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 15386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 15486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // Statistics. 15586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines AsanStats &thread_stats = GetCurrentThreadStats(); 15686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines thread_stats.real_frees++; 15786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines thread_stats.really_freed += m->UsedSize(); 15886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 15986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines get_allocator().Deallocate(cache_, p); 16086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 16186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 16286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines void *Allocate(uptr size) { 16386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return get_allocator().Allocate(cache_, size, 1, false); 16486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 16586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 16686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines void Deallocate(void *p) { 16786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines get_allocator().Deallocate(cache_, p); 16886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 16986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 17086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines AllocatorCache *cache_; 17186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}; 17286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 17386277eb844c4983c81de62d7c050e92fe7155788Stephen Hinestypedef Quarantine<QuarantineCallback, AsanChunk> AsanQuarantine; 17486277eb844c4983c81de62d7c050e92fe7155788Stephen Hinestypedef AsanQuarantine::Cache QuarantineCache; 17586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 17686277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid AsanMapUnmapCallback::OnMap(uptr p, uptr size) const { 17786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines PoisonShadow(p, size, kAsanHeapLeftRedzoneMagic); 17886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // Statistics. 17986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines AsanStats &thread_stats = GetCurrentThreadStats(); 18086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines thread_stats.mmaps++; 18186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines thread_stats.mmaped += size; 18286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 18386277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid AsanMapUnmapCallback::OnUnmap(uptr p, uptr size) const { 18486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines PoisonShadow(p, size, 0); 18586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // We are about to unmap a chunk of user memory. 18686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // Mark the corresponding shadow memory as not needed. 18786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines FlushUnneededASanShadowMemory(p, size); 18886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // Statistics. 18986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines AsanStats &thread_stats = GetCurrentThreadStats(); 19086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines thread_stats.munmaps++; 19186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines thread_stats.munmaped += size; 19286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 19386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 19486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// We can not use THREADLOCAL because it is not supported on some of the 19586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// platforms we care about (OSX 10.6, Android). 19686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// static THREADLOCAL AllocatorCache cache; 19786277eb844c4983c81de62d7c050e92fe7155788Stephen HinesAllocatorCache *GetAllocatorCache(AsanThreadLocalMallocStorage *ms) { 19886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CHECK(ms); 19986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return &ms->allocator_cache; 20086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 20186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 20286277eb844c4983c81de62d7c050e92fe7155788Stephen HinesQuarantineCache *GetQuarantineCache(AsanThreadLocalMallocStorage *ms) { 20386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CHECK(ms); 20486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CHECK_LE(sizeof(QuarantineCache), sizeof(ms->quarantine_cache)); 20586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return reinterpret_cast<QuarantineCache *>(ms->quarantine_cache); 20686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 20786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 20886277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid AllocatorOptions::SetFrom(const Flags *f, const CommonFlags *cf) { 20986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines quarantine_size_mb = f->quarantine_size_mb; 21086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines min_redzone = f->redzone; 21186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines max_redzone = f->max_redzone; 21286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines may_return_null = cf->allocator_may_return_null; 21386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines alloc_dealloc_mismatch = f->alloc_dealloc_mismatch; 21486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 21586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 21686277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid AllocatorOptions::CopyTo(Flags *f, CommonFlags *cf) { 21786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines f->quarantine_size_mb = quarantine_size_mb; 21886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines f->redzone = min_redzone; 21986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines f->max_redzone = max_redzone; 22086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines cf->allocator_may_return_null = may_return_null; 22186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines f->alloc_dealloc_mismatch = alloc_dealloc_mismatch; 22286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 22386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 22486277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstruct Allocator { 22586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines static const uptr kMaxAllowedMallocSize = 226cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar FIRST_32_SECOND_64(3UL << 30, 1UL << 40); 22786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines static const uptr kMaxThreadLocalQuarantine = 22886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines FIRST_32_SECOND_64(1 << 18, 1 << 20); 22986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 23086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines AsanAllocator allocator; 23186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines AsanQuarantine quarantine; 23286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines StaticSpinMutex fallback_mutex; 23386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines AllocatorCache fallback_allocator_cache; 23486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines QuarantineCache fallback_quarantine_cache; 23586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 23686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // ------------------- Options -------------------------- 23786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines atomic_uint16_t min_redzone; 23886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines atomic_uint16_t max_redzone; 23986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines atomic_uint8_t alloc_dealloc_mismatch; 24086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 24186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // ------------------- Initialization ------------------------ 24286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines explicit Allocator(LinkerInitialized) 24386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines : quarantine(LINKER_INITIALIZED), 24486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines fallback_quarantine_cache(LINKER_INITIALIZED) {} 24586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 24686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines void CheckOptions(const AllocatorOptions &options) const { 24786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CHECK_GE(options.min_redzone, 16); 24886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CHECK_GE(options.max_redzone, options.min_redzone); 24986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CHECK_LE(options.max_redzone, 2048); 25086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CHECK(IsPowerOfTwo(options.min_redzone)); 25186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CHECK(IsPowerOfTwo(options.max_redzone)); 25286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 25386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 25486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines void SharedInitCode(const AllocatorOptions &options) { 25586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CheckOptions(options); 25686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines quarantine.Init((uptr)options.quarantine_size_mb << 20, 25786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines kMaxThreadLocalQuarantine); 25886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines atomic_store(&alloc_dealloc_mismatch, options.alloc_dealloc_mismatch, 25986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines memory_order_release); 26086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines atomic_store(&min_redzone, options.min_redzone, memory_order_release); 26186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines atomic_store(&max_redzone, options.max_redzone, memory_order_release); 26286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 26386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 26486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines void Initialize(const AllocatorOptions &options) { 26586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines allocator.Init(options.may_return_null); 26686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines SharedInitCode(options); 26786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 26886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 26986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines void ReInitialize(const AllocatorOptions &options) { 27086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines allocator.SetMayReturnNull(options.may_return_null); 27186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines SharedInitCode(options); 27286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 27386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 27486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines void GetOptions(AllocatorOptions *options) const { 27586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines options->quarantine_size_mb = quarantine.GetSize() >> 20; 27686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines options->min_redzone = atomic_load(&min_redzone, memory_order_acquire); 27786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines options->max_redzone = atomic_load(&max_redzone, memory_order_acquire); 27886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines options->may_return_null = allocator.MayReturnNull(); 27986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines options->alloc_dealloc_mismatch = 28086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines atomic_load(&alloc_dealloc_mismatch, memory_order_acquire); 28186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 28286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 28386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // -------------------- Helper methods. ------------------------- 28486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines uptr ComputeRZLog(uptr user_requested_size) { 28586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines u32 rz_log = 28686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines user_requested_size <= 64 - 16 ? 0 : 28786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines user_requested_size <= 128 - 32 ? 1 : 28886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines user_requested_size <= 512 - 64 ? 2 : 28986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines user_requested_size <= 4096 - 128 ? 3 : 29086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines user_requested_size <= (1 << 14) - 256 ? 4 : 29186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines user_requested_size <= (1 << 15) - 512 ? 5 : 29286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines user_requested_size <= (1 << 16) - 1024 ? 6 : 7; 29386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines u32 min_rz = atomic_load(&min_redzone, memory_order_acquire); 29486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines u32 max_rz = atomic_load(&max_redzone, memory_order_acquire); 29586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return Min(Max(rz_log, RZSize2Log(min_rz)), RZSize2Log(max_rz)); 29686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 29786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 29886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // We have an address between two chunks, and we want to report just one. 29986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines AsanChunk *ChooseChunk(uptr addr, AsanChunk *left_chunk, 30086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines AsanChunk *right_chunk) { 30186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // Prefer an allocated chunk over freed chunk and freed chunk 30286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // over available chunk. 30386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (left_chunk->chunk_state != right_chunk->chunk_state) { 30486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (left_chunk->chunk_state == CHUNK_ALLOCATED) 30586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return left_chunk; 30686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (right_chunk->chunk_state == CHUNK_ALLOCATED) 30786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return right_chunk; 30886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (left_chunk->chunk_state == CHUNK_QUARANTINE) 30986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return left_chunk; 31086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (right_chunk->chunk_state == CHUNK_QUARANTINE) 31186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return right_chunk; 31286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 31386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // Same chunk_state: choose based on offset. 31486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines sptr l_offset = 0, r_offset = 0; 31586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CHECK(AsanChunkView(left_chunk).AddrIsAtRight(addr, 1, &l_offset)); 31686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CHECK(AsanChunkView(right_chunk).AddrIsAtLeft(addr, 1, &r_offset)); 31786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (l_offset < r_offset) 31886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return left_chunk; 31986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return right_chunk; 32086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 32186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 32286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // -------------------- Allocation/Deallocation routines --------------- 32386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines void *Allocate(uptr size, uptr alignment, BufferedStackTrace *stack, 32486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines AllocType alloc_type, bool can_fill) { 32586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (UNLIKELY(!asan_inited)) 32686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines AsanInitFromRtl(); 32786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines Flags &fl = *flags(); 32886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CHECK(stack); 32986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines const uptr min_alignment = SHADOW_GRANULARITY; 33086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (alignment < min_alignment) 33186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines alignment = min_alignment; 33286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (size == 0) { 33386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // We'd be happy to avoid allocating memory for zero-size requests, but 33486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // some programs/tests depend on this behavior and assume that malloc 33586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // would not return NULL even for zero-size allocations. Moreover, it 33686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // looks like operator new should never return NULL, and results of 33786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // consecutive "new" calls must be different even if the allocated size 33886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // is zero. 33986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines size = 1; 34086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 34186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CHECK(IsPowerOfTwo(alignment)); 34286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines uptr rz_log = ComputeRZLog(size); 34386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines uptr rz_size = RZLog2Size(rz_log); 34486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines uptr rounded_size = RoundUpTo(Max(size, kChunkHeader2Size), alignment); 34586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines uptr needed_size = rounded_size + rz_size; 34686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (alignment > min_alignment) 34786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines needed_size += alignment; 34886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines bool using_primary_allocator = true; 34986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // If we are allocating from the secondary allocator, there will be no 35086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // automatic right redzone, so add the right redzone manually. 35186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (!PrimaryAllocator::CanAllocate(needed_size, alignment)) { 35286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines needed_size += rz_size; 35386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines using_primary_allocator = false; 35486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 35586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CHECK(IsAligned(needed_size, min_alignment)); 35686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (size > kMaxAllowedMallocSize || needed_size > kMaxAllowedMallocSize) { 357cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar Report("WARNING: AddressSanitizer failed to allocate 0x%zx bytes\n", 35886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines (void*)size); 35986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return allocator.ReturnNullOrDie(); 36086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 36186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 36286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines AsanThread *t = GetCurrentThread(); 36386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines void *allocated; 36486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines bool check_rss_limit = true; 36586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (t) { 36686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines AllocatorCache *cache = GetAllocatorCache(&t->malloc_storage()); 36786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines allocated = 36886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines allocator.Allocate(cache, needed_size, 8, false, check_rss_limit); 36986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } else { 37086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines SpinMutexLock l(&fallback_mutex); 37186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines AllocatorCache *cache = &fallback_allocator_cache; 37286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines allocated = 37386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines allocator.Allocate(cache, needed_size, 8, false, check_rss_limit); 37486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 37586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 37686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (!allocated) 37786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return allocator.ReturnNullOrDie(); 37886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 37986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (*(u8 *)MEM_TO_SHADOW((uptr)allocated) == 0 && CanPoisonMemory()) { 38086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // Heap poisoning is enabled, but the allocator provides an unpoisoned 38186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // chunk. This is possible if CanPoisonMemory() was false for some 38286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // time, for example, due to flags()->start_disabled. 38386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // Anyway, poison the block before using it for anything else. 38486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines uptr allocated_size = allocator.GetActuallyAllocatedSize(allocated); 38586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines PoisonShadow((uptr)allocated, allocated_size, kAsanHeapLeftRedzoneMagic); 38686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 38786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 38886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines uptr alloc_beg = reinterpret_cast<uptr>(allocated); 38986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines uptr alloc_end = alloc_beg + needed_size; 39086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines uptr beg_plus_redzone = alloc_beg + rz_size; 39186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines uptr user_beg = beg_plus_redzone; 39286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (!IsAligned(user_beg, alignment)) 39386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines user_beg = RoundUpTo(user_beg, alignment); 39486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines uptr user_end = user_beg + size; 39586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CHECK_LE(user_end, alloc_end); 39686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines uptr chunk_beg = user_beg - kChunkHeaderSize; 39786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines AsanChunk *m = reinterpret_cast<AsanChunk *>(chunk_beg); 39886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines m->alloc_type = alloc_type; 39986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines m->rz_log = rz_log; 40086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines u32 alloc_tid = t ? t->tid() : 0; 40186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines m->alloc_tid = alloc_tid; 40286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CHECK_EQ(alloc_tid, m->alloc_tid); // Does alloc_tid fit into the bitfield? 40386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines m->free_tid = kInvalidTid; 40486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines m->from_memalign = user_beg != beg_plus_redzone; 40586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (alloc_beg != chunk_beg) { 40686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CHECK_LE(alloc_beg+ 2 * sizeof(uptr), chunk_beg); 40786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines reinterpret_cast<uptr *>(alloc_beg)[0] = kAllocBegMagic; 40886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines reinterpret_cast<uptr *>(alloc_beg)[1] = chunk_beg; 40986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 41086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (using_primary_allocator) { 41186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CHECK(size); 41286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines m->user_requested_size = size; 41386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CHECK(allocator.FromPrimary(allocated)); 41486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } else { 41586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CHECK(!allocator.FromPrimary(allocated)); 41686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines m->user_requested_size = SizeClassMap::kMaxSize; 41786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines uptr *meta = reinterpret_cast<uptr *>(allocator.GetMetaData(allocated)); 41886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines meta[0] = size; 41986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines meta[1] = chunk_beg; 42086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 42186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 42286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines m->alloc_context_id = StackDepotPut(*stack); 42386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 42486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines uptr size_rounded_down_to_granularity = 42586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines RoundDownTo(size, SHADOW_GRANULARITY); 42686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // Unpoison the bulk of the memory region. 42786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (size_rounded_down_to_granularity) 42886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines PoisonShadow(user_beg, size_rounded_down_to_granularity, 0); 42986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // Deal with the end of the region if size is not aligned to granularity. 43086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (size != size_rounded_down_to_granularity && CanPoisonMemory()) { 43186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines u8 *shadow = 43286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines (u8 *)MemToShadow(user_beg + size_rounded_down_to_granularity); 43386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines *shadow = fl.poison_partial ? (size & (SHADOW_GRANULARITY - 1)) : 0; 43486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 43586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 43686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines AsanStats &thread_stats = GetCurrentThreadStats(); 43786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines thread_stats.mallocs++; 43886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines thread_stats.malloced += size; 43986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines thread_stats.malloced_redzones += needed_size - size; 44086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (needed_size > SizeClassMap::kMaxSize) 44186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines thread_stats.malloc_large++; 4423d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar else 4433d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar thread_stats.malloced_by_size[SizeClassMap::ClassID(needed_size)]++; 44486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 44586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines void *res = reinterpret_cast<void *>(user_beg); 44686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (can_fill && fl.max_malloc_fill_size) { 44786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines uptr fill_size = Min(size, (uptr)fl.max_malloc_fill_size); 44886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines REAL(memset)(res, fl.malloc_fill_byte, fill_size); 44986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 45086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if CAN_SANITIZE_LEAKS 45186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines m->lsan_tag = __lsan::DisabledInThisThread() ? __lsan::kIgnored 45286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines : __lsan::kDirectlyLeaked; 45386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#endif 45486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // Must be the last mutation of metadata in this function. 45586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines atomic_store((atomic_uint8_t *)m, CHUNK_ALLOCATED, memory_order_release); 45686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines ASAN_MALLOC_HOOK(res, size); 45786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return res; 45886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 45986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 46086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines void AtomicallySetQuarantineFlag(AsanChunk *m, void *ptr, 46186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines BufferedStackTrace *stack) { 46286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines u8 old_chunk_state = CHUNK_ALLOCATED; 46386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // Flip the chunk_state atomically to avoid race on double-free. 46486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (!atomic_compare_exchange_strong((atomic_uint8_t*)m, &old_chunk_state, 46586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CHUNK_QUARANTINE, memory_order_acquire)) 46686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines ReportInvalidFree(ptr, old_chunk_state, stack); 46786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CHECK_EQ(CHUNK_ALLOCATED, old_chunk_state); 46886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 46986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 47086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // Expects the chunk to already be marked as quarantined by using 47186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // AtomicallySetQuarantineFlag. 47286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines void QuarantineChunk(AsanChunk *m, void *ptr, BufferedStackTrace *stack, 47386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines AllocType alloc_type) { 47486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CHECK_EQ(m->chunk_state, CHUNK_QUARANTINE); 47586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 47686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (m->alloc_type != alloc_type) { 47786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (atomic_load(&alloc_dealloc_mismatch, memory_order_acquire)) { 47886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines ReportAllocTypeMismatch((uptr)ptr, stack, (AllocType)m->alloc_type, 47986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines (AllocType)alloc_type); 48086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 48186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 48286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 48386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CHECK_GE(m->alloc_tid, 0); 48486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (SANITIZER_WORDSIZE == 64) // On 32-bits this resides in user area. 48586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CHECK_EQ(m->free_tid, kInvalidTid); 48686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines AsanThread *t = GetCurrentThread(); 48786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines m->free_tid = t ? t->tid() : 0; 48886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines m->free_context_id = StackDepotPut(*stack); 48986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // Poison the region. 49086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines PoisonShadow(m->Beg(), 49186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines RoundUpTo(m->UsedSize(), SHADOW_GRANULARITY), 49286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines kAsanHeapFreeMagic); 49386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 49486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines AsanStats &thread_stats = GetCurrentThreadStats(); 49586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines thread_stats.frees++; 49686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines thread_stats.freed += m->UsedSize(); 49786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 49886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // Push into quarantine. 49986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (t) { 50086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines AsanThreadLocalMallocStorage *ms = &t->malloc_storage(); 50186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines AllocatorCache *ac = GetAllocatorCache(ms); 50286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines quarantine.Put(GetQuarantineCache(ms), QuarantineCallback(ac), m, 50386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines m->UsedSize()); 50486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } else { 50586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines SpinMutexLock l(&fallback_mutex); 50686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines AllocatorCache *ac = &fallback_allocator_cache; 50786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines quarantine.Put(&fallback_quarantine_cache, QuarantineCallback(ac), m, 50886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines m->UsedSize()); 50986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 51086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 51186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 51286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines void Deallocate(void *ptr, uptr delete_size, BufferedStackTrace *stack, 51386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines AllocType alloc_type) { 51486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines uptr p = reinterpret_cast<uptr>(ptr); 51586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (p == 0) return; 51686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 51786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines uptr chunk_beg = p - kChunkHeaderSize; 51886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines AsanChunk *m = reinterpret_cast<AsanChunk *>(chunk_beg); 51986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (delete_size && flags()->new_delete_type_mismatch && 52086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines delete_size != m->UsedSize()) { 52186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines ReportNewDeleteSizeMismatch(p, delete_size, stack); 52286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 52386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines ASAN_FREE_HOOK(ptr); 52486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // Must mark the chunk as quarantined before any changes to its metadata. 52586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines AtomicallySetQuarantineFlag(m, ptr, stack); 52686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines QuarantineChunk(m, ptr, stack, alloc_type); 52786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 52886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 52986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines void *Reallocate(void *old_ptr, uptr new_size, BufferedStackTrace *stack) { 53086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CHECK(old_ptr && new_size); 53186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines uptr p = reinterpret_cast<uptr>(old_ptr); 53286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines uptr chunk_beg = p - kChunkHeaderSize; 53386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines AsanChunk *m = reinterpret_cast<AsanChunk *>(chunk_beg); 53486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 53586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines AsanStats &thread_stats = GetCurrentThreadStats(); 53686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines thread_stats.reallocs++; 53786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines thread_stats.realloced += new_size; 53886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 53986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines void *new_ptr = Allocate(new_size, 8, stack, FROM_MALLOC, true); 54086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (new_ptr) { 54186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines u8 chunk_state = m->chunk_state; 54286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (chunk_state != CHUNK_ALLOCATED) 54386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines ReportInvalidFree(old_ptr, chunk_state, stack); 5443d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar CHECK_NE(REAL(memcpy), nullptr); 54586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines uptr memcpy_size = Min(new_size, m->UsedSize()); 54686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // If realloc() races with free(), we may start copying freed memory. 54786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // However, we will report racy double-free later anyway. 54886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines REAL(memcpy)(new_ptr, old_ptr, memcpy_size); 54986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines Deallocate(old_ptr, 0, stack, FROM_MALLOC); 55086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 55186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return new_ptr; 55286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 55386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 55486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines void *Calloc(uptr nmemb, uptr size, BufferedStackTrace *stack) { 55586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (CallocShouldReturnNullDueToOverflow(size, nmemb)) 55686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return allocator.ReturnNullOrDie(); 55786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines void *ptr = Allocate(nmemb * size, 8, stack, FROM_MALLOC, false); 55886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // If the memory comes from the secondary allocator no need to clear it 55986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // as it comes directly from mmap. 56086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (ptr && allocator.FromPrimary(ptr)) 56186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines REAL(memset)(ptr, 0, nmemb * size); 56286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return ptr; 56386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 56486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 56586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines void ReportInvalidFree(void *ptr, u8 chunk_state, BufferedStackTrace *stack) { 56686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (chunk_state == CHUNK_QUARANTINE) 56786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines ReportDoubleFree((uptr)ptr, stack); 56886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines else 56986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines ReportFreeNotMalloced((uptr)ptr, stack); 57086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 57186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 57286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines void CommitBack(AsanThreadLocalMallocStorage *ms) { 57386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines AllocatorCache *ac = GetAllocatorCache(ms); 57486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines quarantine.Drain(GetQuarantineCache(ms), QuarantineCallback(ac)); 57586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines allocator.SwallowCache(ac); 57686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 57786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 57886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // -------------------------- Chunk lookup ---------------------- 57986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 58086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // Assumes alloc_beg == allocator.GetBlockBegin(alloc_beg). 58186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines AsanChunk *GetAsanChunk(void *alloc_beg) { 5823d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar if (!alloc_beg) return nullptr; 58386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (!allocator.FromPrimary(alloc_beg)) { 58486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines uptr *meta = reinterpret_cast<uptr *>(allocator.GetMetaData(alloc_beg)); 58586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines AsanChunk *m = reinterpret_cast<AsanChunk *>(meta[1]); 58686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return m; 58786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 58886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines uptr *alloc_magic = reinterpret_cast<uptr *>(alloc_beg); 58986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (alloc_magic[0] == kAllocBegMagic) 59086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return reinterpret_cast<AsanChunk *>(alloc_magic[1]); 59186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return reinterpret_cast<AsanChunk *>(alloc_beg); 59286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 59386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 59486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines AsanChunk *GetAsanChunkByAddr(uptr p) { 59586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines void *alloc_beg = allocator.GetBlockBegin(reinterpret_cast<void *>(p)); 59686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return GetAsanChunk(alloc_beg); 59786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 59886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 59986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // Allocator must be locked when this function is called. 60086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines AsanChunk *GetAsanChunkByAddrFastLocked(uptr p) { 60186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines void *alloc_beg = 60286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines allocator.GetBlockBeginFastLocked(reinterpret_cast<void *>(p)); 60386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return GetAsanChunk(alloc_beg); 60486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 60586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 60686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines uptr AllocationSize(uptr p) { 60786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines AsanChunk *m = GetAsanChunkByAddr(p); 60886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (!m) return 0; 60986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (m->chunk_state != CHUNK_ALLOCATED) return 0; 61086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (m->Beg() != p) return 0; 61186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return m->UsedSize(); 61286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 61386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 61486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines AsanChunkView FindHeapChunkByAddress(uptr addr) { 61586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines AsanChunk *m1 = GetAsanChunkByAddr(addr); 61686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (!m1) return AsanChunkView(m1); 61786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines sptr offset = 0; 61886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (AsanChunkView(m1).AddrIsAtLeft(addr, 1, &offset)) { 61986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // The address is in the chunk's left redzone, so maybe it is actually 62086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // a right buffer overflow from the other chunk to the left. 62186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // Search a bit to the left to see if there is another chunk. 6223d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar AsanChunk *m2 = nullptr; 62386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines for (uptr l = 1; l < GetPageSizeCached(); l++) { 62486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines m2 = GetAsanChunkByAddr(addr - l); 62586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (m2 == m1) continue; // Still the same chunk. 62686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines break; 62786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 62886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (m2 && AsanChunkView(m2).AddrIsAtRight(addr, 1, &offset)) 62986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines m1 = ChooseChunk(addr, m2, m1); 63086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 63186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return AsanChunkView(m1); 63286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 63386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 63486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines void PrintStats() { 63586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines allocator.PrintStats(); 63686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 63786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 63886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines void ForceLock() { 63986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines allocator.ForceLock(); 64086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines fallback_mutex.Lock(); 64186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 64286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 64386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines void ForceUnlock() { 64486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines fallback_mutex.Unlock(); 64586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines allocator.ForceUnlock(); 64686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 64786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}; 64886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 64986277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstatic Allocator instance(LINKER_INITIALIZED); 65086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 65186277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstatic AsanAllocator &get_allocator() { 65286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return instance.allocator; 65386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 65486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 65586277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesbool AsanChunkView::IsValid() { 6563d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar return chunk_ && chunk_->chunk_state != CHUNK_AVAILABLE; 65786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 65886277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesuptr AsanChunkView::Beg() { return chunk_->Beg(); } 65986277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesuptr AsanChunkView::End() { return Beg() + UsedSize(); } 66086277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesuptr AsanChunkView::UsedSize() { return chunk_->UsedSize(); } 66186277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesuptr AsanChunkView::AllocTid() { return chunk_->alloc_tid; } 66286277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesuptr AsanChunkView::FreeTid() { return chunk_->free_tid; } 66386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 66486277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstatic StackTrace GetStackTraceFromId(u32 id) { 66586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CHECK(id); 66686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines StackTrace res = StackDepotGet(id); 66786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CHECK(res.trace); 66886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return res; 66986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 67086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 67186277eb844c4983c81de62d7c050e92fe7155788Stephen HinesStackTrace AsanChunkView::GetAllocStack() { 67286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return GetStackTraceFromId(chunk_->alloc_context_id); 67386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 67486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 67586277eb844c4983c81de62d7c050e92fe7155788Stephen HinesStackTrace AsanChunkView::GetFreeStack() { 67686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return GetStackTraceFromId(chunk_->free_context_id); 67786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 67886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 67986277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid InitializeAllocator(const AllocatorOptions &options) { 68086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines instance.Initialize(options); 68186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 68286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 68386277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid ReInitializeAllocator(const AllocatorOptions &options) { 68486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines instance.ReInitialize(options); 68586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 68686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 68786277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid GetAllocatorOptions(AllocatorOptions *options) { 68886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines instance.GetOptions(options); 68986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 69086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 69186277eb844c4983c81de62d7c050e92fe7155788Stephen HinesAsanChunkView FindHeapChunkByAddress(uptr addr) { 69286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return instance.FindHeapChunkByAddress(addr); 69386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 69486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 69586277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid AsanThreadLocalMallocStorage::CommitBack() { 69686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines instance.CommitBack(this); 69786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 69886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 69986277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid PrintInternalAllocatorStats() { 70086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines instance.PrintStats(); 70186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 70286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 70386277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid *asan_memalign(uptr alignment, uptr size, BufferedStackTrace *stack, 70486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines AllocType alloc_type) { 70586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return instance.Allocate(size, alignment, stack, alloc_type, true); 70686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 70786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 70886277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid asan_free(void *ptr, BufferedStackTrace *stack, AllocType alloc_type) { 70986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines instance.Deallocate(ptr, 0, stack, alloc_type); 71086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 71186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 71286277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid asan_sized_free(void *ptr, uptr size, BufferedStackTrace *stack, 71386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines AllocType alloc_type) { 71486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines instance.Deallocate(ptr, size, stack, alloc_type); 71586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 71686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 71786277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid *asan_malloc(uptr size, BufferedStackTrace *stack) { 71886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return instance.Allocate(size, 8, stack, FROM_MALLOC, true); 71986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 72086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 72186277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid *asan_calloc(uptr nmemb, uptr size, BufferedStackTrace *stack) { 72286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return instance.Calloc(nmemb, size, stack); 72386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 72486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 72586277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid *asan_realloc(void *p, uptr size, BufferedStackTrace *stack) { 7263d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar if (!p) 72786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return instance.Allocate(size, 8, stack, FROM_MALLOC, true); 72886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (size == 0) { 72986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines instance.Deallocate(p, 0, stack, FROM_MALLOC); 7303d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar return nullptr; 73186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 73286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return instance.Reallocate(p, size, stack); 73386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 73486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 73586277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid *asan_valloc(uptr size, BufferedStackTrace *stack) { 73686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return instance.Allocate(size, GetPageSizeCached(), stack, FROM_MALLOC, true); 73786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 73886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 73986277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid *asan_pvalloc(uptr size, BufferedStackTrace *stack) { 74086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines uptr PageSize = GetPageSizeCached(); 74186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines size = RoundUpTo(size, PageSize); 74286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (size == 0) { 74386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // pvalloc(0) should allocate one page. 74486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines size = PageSize; 74586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 74686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return instance.Allocate(size, PageSize, stack, FROM_MALLOC, true); 74786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 74886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 74986277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesint asan_posix_memalign(void **memptr, uptr alignment, uptr size, 75086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines BufferedStackTrace *stack) { 75186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines void *ptr = instance.Allocate(size, alignment, stack, FROM_MALLOC, true); 75286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CHECK(IsAligned((uptr)ptr, alignment)); 75386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines *memptr = ptr; 75486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return 0; 75586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 75686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 75786277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesuptr asan_malloc_usable_size(void *ptr, uptr pc, uptr bp) { 7583d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar if (!ptr) return 0; 75986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines uptr usable_size = instance.AllocationSize(reinterpret_cast<uptr>(ptr)); 76086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (flags()->check_malloc_usable_size && (usable_size == 0)) { 76186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines GET_STACK_TRACE_FATAL(pc, bp); 76286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines ReportMallocUsableSizeNotOwned((uptr)ptr, &stack); 76386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 76486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return usable_size; 76586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 76686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 76786277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesuptr asan_mz_size(const void *ptr) { 76886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return instance.AllocationSize(reinterpret_cast<uptr>(ptr)); 76986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 77086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 77186277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid asan_mz_force_lock() { 77286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines instance.ForceLock(); 77386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 77486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 77586277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid asan_mz_force_unlock() { 77686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines instance.ForceUnlock(); 77786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 77886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 77986277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid AsanSoftRssLimitExceededCallback(bool exceeded) { 78086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines instance.allocator.SetRssLimitIsExceeded(exceeded); 78186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 78286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 7833d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar} // namespace __asan 78486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 78586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// --- Implementation of LSan-specific functions --- {{{1 78686277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesnamespace __lsan { 78786277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid LockAllocator() { 78886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines __asan::get_allocator().ForceLock(); 78986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 79086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 79186277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid UnlockAllocator() { 79286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines __asan::get_allocator().ForceUnlock(); 79386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 79486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 79586277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid GetAllocatorGlobalRange(uptr *begin, uptr *end) { 79686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines *begin = (uptr)&__asan::get_allocator(); 79786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines *end = *begin + sizeof(__asan::get_allocator()); 79886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 79986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 80086277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesuptr PointsIntoChunk(void* p) { 80186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines uptr addr = reinterpret_cast<uptr>(p); 80286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines __asan::AsanChunk *m = __asan::instance.GetAsanChunkByAddrFastLocked(addr); 80386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (!m) return 0; 80486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines uptr chunk = m->Beg(); 80586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (m->chunk_state != __asan::CHUNK_ALLOCATED) 80686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return 0; 80786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (m->AddrIsInside(addr, /*locked_version=*/true)) 80886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return chunk; 80986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (IsSpecialCaseOfOperatorNew0(chunk, m->UsedSize(/*locked_version*/ true), 81086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines addr)) 81186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return chunk; 81286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return 0; 81386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 81486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 81586277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesuptr GetUserBegin(uptr chunk) { 81686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines __asan::AsanChunk *m = __asan::instance.GetAsanChunkByAddrFastLocked(chunk); 81786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CHECK(m); 81886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return m->Beg(); 81986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 82086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 82186277eb844c4983c81de62d7c050e92fe7155788Stephen HinesLsanMetadata::LsanMetadata(uptr chunk) { 82286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines metadata_ = reinterpret_cast<void *>(chunk - __asan::kChunkHeaderSize); 82386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 82486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 82586277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesbool LsanMetadata::allocated() const { 82686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines __asan::AsanChunk *m = reinterpret_cast<__asan::AsanChunk *>(metadata_); 82786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return m->chunk_state == __asan::CHUNK_ALLOCATED; 82886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 82986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 83086277eb844c4983c81de62d7c050e92fe7155788Stephen HinesChunkTag LsanMetadata::tag() const { 83186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines __asan::AsanChunk *m = reinterpret_cast<__asan::AsanChunk *>(metadata_); 83286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return static_cast<ChunkTag>(m->lsan_tag); 83386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 83486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 83586277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid LsanMetadata::set_tag(ChunkTag value) { 83686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines __asan::AsanChunk *m = reinterpret_cast<__asan::AsanChunk *>(metadata_); 83786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines m->lsan_tag = value; 83886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 83986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 84086277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesuptr LsanMetadata::requested_size() const { 84186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines __asan::AsanChunk *m = reinterpret_cast<__asan::AsanChunk *>(metadata_); 84286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return m->UsedSize(/*locked_version=*/true); 84386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 84486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 84586277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesu32 LsanMetadata::stack_trace_id() const { 84686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines __asan::AsanChunk *m = reinterpret_cast<__asan::AsanChunk *>(metadata_); 84786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return m->alloc_context_id; 84886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 84986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 85086277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid ForEachChunk(ForEachChunkCallback callback, void *arg) { 85186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines __asan::get_allocator().ForEachChunk(callback, arg); 85286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 85386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 85486277eb844c4983c81de62d7c050e92fe7155788Stephen HinesIgnoreObjectResult IgnoreObjectLocked(const void *p) { 85586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines uptr addr = reinterpret_cast<uptr>(p); 85686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines __asan::AsanChunk *m = __asan::instance.GetAsanChunkByAddr(addr); 85786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (!m) return kIgnoreObjectInvalid; 85886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if ((m->chunk_state == __asan::CHUNK_ALLOCATED) && m->AddrIsInside(addr)) { 85986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (m->lsan_tag == kIgnored) 86086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return kIgnoreObjectAlreadyIgnored; 86186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines m->lsan_tag = __lsan::kIgnored; 86286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return kIgnoreObjectSuccess; 86386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } else { 86486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return kIgnoreObjectInvalid; 86586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 86686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 86786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} // namespace __lsan 86886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 86986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// ---------------------- Interface ---------------- {{{1 87086277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesusing namespace __asan; // NOLINT 87186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 87286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// ASan allocator doesn't reserve extra bytes, so normally we would 87386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// just return "size". We don't want to expose our redzone sizes, etc here. 87486277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesuptr __sanitizer_get_estimated_allocated_size(uptr size) { 87586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return size; 87686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 87786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 87886277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesint __sanitizer_get_ownership(const void *p) { 87986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines uptr ptr = reinterpret_cast<uptr>(p); 88086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return instance.AllocationSize(ptr) > 0; 88186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 88286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 88386277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesuptr __sanitizer_get_allocated_size(const void *p) { 8843d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar if (!p) return 0; 88586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines uptr ptr = reinterpret_cast<uptr>(p); 88686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines uptr allocated_size = instance.AllocationSize(ptr); 88786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // Die if p is not malloced or if it is already freed. 88886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (allocated_size == 0) { 88986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines GET_STACK_TRACE_FATAL_HERE; 89086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines ReportSanitizerGetAllocatedSizeNotOwned(ptr, &stack); 89186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 89286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return allocated_size; 89386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 89486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 89586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if !SANITIZER_SUPPORTS_WEAK_HOOKS 89686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// Provide default (no-op) implementation of malloc hooks. 89786277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesextern "C" { 89886277eb844c4983c81de62d7c050e92fe7155788Stephen HinesSANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE 89986277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid __sanitizer_malloc_hook(void *ptr, uptr size) { 90086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines (void)ptr; 90186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines (void)size; 90286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 90386277eb844c4983c81de62d7c050e92fe7155788Stephen HinesSANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE 90486277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid __sanitizer_free_hook(void *ptr) { 90586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines (void)ptr; 90686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 9073d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar} // extern "C" 90886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#endif 909