asan_malloc_mac.cc revision 0aa794d78fbb6359f81025217559f1b03ff07999
1e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard//===-- asan_rtl.cc -------------------------------------------------------===// 2e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard// 3e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard// The LLVM Compiler Infrastructure 4e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard// 5e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard// This file is distributed under the University of Illinois Open Source 6e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard// License. See LICENSE.TXT for details. 7e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard// 8e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard//===----------------------------------------------------------------------===// 9e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard// 10e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard// This file is a part of AddressSanitizer, an address sanity checker. 11e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard// 12e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard// Mac-specific malloc interception. 13e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard//===----------------------------------------------------------------------===// 14e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 15e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#ifdef __APPLE__ 16e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 17e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include <AvailabilityMacros.h> 18e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include <CoreFoundation/CFBase.h> 19e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include <malloc/malloc.h> 20e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include <setjmp.h> 21956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 22956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include "asan_allocator.h" 23e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include "asan_interceptors.h" 24956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include "asan_internal.h" 25956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include "asan_stack.h" 26956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 27e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard// Similar code is used in Google Perftools, 28e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard// http://code.google.com/p/google-perftools. 29e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 30e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard// ---------------------- Replacement functions ---------------- {{{1 31e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardusing namespace __asan; // NOLINT 32e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 33e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard// TODO(glider): do we need both zones? 34b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgardstatic malloc_zone_t *system_malloc_zone = 0; 35956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic malloc_zone_t *system_purgeable_zone = 0; 36956c553ab0ce72f8074ad0fda2ffd66a0305700cJames DongCFAllocatorRef cf_asan = 0; 37956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 38956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong// The free() implementation provided by OS X calls malloc_zone_from_ptr() 39956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong// to find the owner of |ptr|. If the result is 0, an invalid free() is 40956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong// reported. Our implementation falls back to asan_free() in this case 41956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong// in order to print an ASan-style report. 42e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard// 43e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard// For the objects created by _CFRuntimeCreateInstance a CFAllocatorRef is 44e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard// placed at the beginning of the allocated chunk and the pointer returned by 45e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard// our allocator is off by sizeof(CFAllocatorRef). This pointer can be then 46e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard// passed directly to free(), which will lead to errors. 47e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard// To overcome this we're checking whether |ptr-sizeof(CFAllocatorRef)| 48e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard// contains a pointer to our CFAllocator (assuming no other allocator is used). 49e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard// See http://code.google.com/p/address-sanitizer/issues/detail?id=70 for more 50b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard// info. 51e2e838afcf03e603a41a0455846eaf9614537c16Mans RullgardINTERCEPTOR(void, free, void *ptr) { 52e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard malloc_zone_t *zone = malloc_zone_from_ptr(ptr); 53e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard if (zone) { 54b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard#if defined(MAC_OS_X_VERSION_10_6) && \ 55b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 56b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard if ((zone->version >= 6) && (zone->free_definite_size)) { 57b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard zone->free_definite_size(zone, ptr, malloc_size(ptr)); 58e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } else { 59e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard malloc_zone_free(zone, ptr); 60e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } 61b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard#else 62e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard malloc_zone_free(zone, ptr); 63e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#endif 64e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } else { 65e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard if (FLAG_replace_cfallocator) { 66956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong // Make sure we're not hitting the previous page. This may be incorrect 67956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong // if ASan's malloc returns an address ending with 0xFF8, which will be 68956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong // then padded to a page boundary with a CFAllocatorRef. 69956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong uptr arith_ptr = (uptr)ptr; 70956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if ((arith_ptr & 0xFFF) > sizeof(CFAllocatorRef)) { 71956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong CFAllocatorRef *saved = 72e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard (CFAllocatorRef*)(arith_ptr - sizeof(CFAllocatorRef)); 73e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard if ((*saved == cf_asan) && asan_mz_size(saved)) ptr = (void*)saved; 74e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } 75e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } 76e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard GET_STACK_TRACE_HERE_FOR_FREE(ptr); 77b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard asan_free(ptr, &stack); 78b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard } 79e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard} 80e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 81e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardnamespace { 82e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard// TODO(glider): the mz_* functions should be united with the Linux wrappers, 83e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard// as they are basically copied from there. 84e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardsize_t mz_size(malloc_zone_t* zone, const void* ptr) { 85e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard // Fast path: check whether this pointer belongs to the original malloc zone. 86e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard // We cannot just call malloc_zone_from_ptr(), because it in turn 87e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard // calls our mz_size(). 88e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard if (system_malloc_zone) { 89e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard if ((system_malloc_zone->size)(system_malloc_zone, ptr)) return 0; 90e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } 91e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard return asan_mz_size(ptr); 92e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard} 93e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 94e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardvoid *mz_malloc(malloc_zone_t *zone, size_t size) { 95e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard if (!asan_inited) { 96e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard CHECK(system_malloc_zone); 97e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard return malloc_zone_malloc(system_malloc_zone, size); 98e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } 99e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard GET_STACK_TRACE_HERE_FOR_MALLOC; 100e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard return asan_malloc(size, &stack); 101e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard} 102956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 103956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongvoid *cf_malloc(CFIndex size, CFOptionFlags hint, void *info) { 104956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (!asan_inited) { 105956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong CHECK(system_malloc_zone); 106956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return malloc_zone_malloc(system_malloc_zone, size); 107e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } 108e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard GET_STACK_TRACE_HERE_FOR_MALLOC; 109e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard return asan_malloc(size, &stack); 110e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard} 111e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 112e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardvoid *mz_calloc(malloc_zone_t *zone, size_t nmemb, size_t size) { 113e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard if (!asan_inited) { 114e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym. 115e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard const size_t kCallocPoolSize = 1024; 116b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard static uptr calloc_memory_for_dlsym[kCallocPoolSize]; 117e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard static size_t allocated; 118e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard size_t size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize; 119e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard void *mem = (void*)&calloc_memory_for_dlsym[allocated]; 120e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard allocated += size_in_words; 121e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard CHECK(allocated < kCallocPoolSize); 122e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard return mem; 123e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } 124e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard GET_STACK_TRACE_HERE_FOR_MALLOC; 125e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard return asan_calloc(nmemb, size, &stack); 126e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard} 127e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 128e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardvoid *mz_valloc(malloc_zone_t *zone, size_t size) { 129e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard if (!asan_inited) { 130e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard CHECK(system_malloc_zone); 131e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard return malloc_zone_valloc(system_malloc_zone, size); 132e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } 133e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard GET_STACK_TRACE_HERE_FOR_MALLOC; 134e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard return asan_memalign(kPageSize, size, &stack); 135e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard} 136e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 137e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardvoid print_zone_for_ptr(void *ptr) { 138e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard malloc_zone_t *orig_zone = malloc_zone_from_ptr(ptr); 139e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard if (orig_zone) { 140e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard if (orig_zone->zone_name) { 141e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard AsanPrintf("malloc_zone_from_ptr(%p) = %p, which is %s\n", 142e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ptr, orig_zone, orig_zone->zone_name); 143e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } else { 144e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard AsanPrintf("malloc_zone_from_ptr(%p) = %p, which doesn't have a name\n", 145e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ptr, orig_zone); 146e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } 147e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } else { 148e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard AsanPrintf("malloc_zone_from_ptr(%p) = 0\n", ptr); 149e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } 150e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard} 151e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 152e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardvoid ALWAYS_INLINE free_common(void *context, void *ptr) { 153e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard if (!ptr) return; 154e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard malloc_zone_t *orig_zone = malloc_zone_from_ptr(ptr); 155e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard // For some reason Chromium calls mz_free() for pointers that belong to 156e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard // DefaultPurgeableMallocZone instead of asan_zone. We might want to 157e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard // fix this someday. 158e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard if (orig_zone == system_purgeable_zone) { 159e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard system_purgeable_zone->free(system_purgeable_zone, ptr); 160e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard return; 161e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } 162e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard if (!FLAG_mac_ignore_invalid_free || asan_mz_size(ptr)) { 163e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard GET_STACK_TRACE_HERE_FOR_FREE(ptr); 164e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard asan_free(ptr, &stack); 165e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } else { 166e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard // Let us just leak this memory for now. 167e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard AsanPrintf("free_common(%p) -- attempting to free unallocated memory.\n" 168e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard "AddressSanitizer is ignoring this error on Mac OS now.\n", 169e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ptr); 170e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard print_zone_for_ptr(ptr); 171e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard GET_STACK_TRACE_HERE_FOR_FREE(ptr); 172e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard stack.PrintStack(); 173e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard return; 174e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } 175e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard} 176e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 177e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard// TODO(glider): the allocation callbacks need to be refactored. 178e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardvoid mz_free(malloc_zone_t *zone, void *ptr) { 179e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard free_common(zone, ptr); 180e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard} 181e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 182956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongvoid cf_free(void *ptr, void *info) { 183956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong free_common(info, ptr); 184956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 185956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 186956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongvoid *mz_realloc(malloc_zone_t *zone, void *ptr, size_t size) { 187e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard if (!ptr) { 188e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard GET_STACK_TRACE_HERE_FOR_MALLOC; 189e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard return asan_malloc(size, &stack); 190e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } else { 191e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard if (asan_mz_size(ptr)) { 192e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard GET_STACK_TRACE_HERE_FOR_MALLOC; 193e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard return asan_realloc(ptr, size, &stack); 194e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } else { 195e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard // We can't recover from reallocating an unknown address, because 196e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard // this would require reading at most |size| bytes from 197b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard // potentially unaccessible memory. 198e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard AsanPrintf("mz_realloc(%p) -- attempting to realloc unallocated memory.\n" 199e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard "This is an unrecoverable problem, exiting now.\n", 200e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ptr); 201e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard print_zone_for_ptr(ptr); 202b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard GET_STACK_TRACE_HERE_FOR_FREE(ptr); 203e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard stack.PrintStack(); 204e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ShowStatsAndAbort(); 205e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard return 0; // unreachable 206b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard } 207e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } 208e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard} 209e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 210e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardvoid *cf_realloc(void *ptr, CFIndex size, CFOptionFlags hint, void *info) { 211b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard if (!ptr) { 212e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard GET_STACK_TRACE_HERE_FOR_MALLOC; 213b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard return asan_malloc(size, &stack); 214e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } else { 215e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard if (asan_mz_size(ptr)) { 216e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard GET_STACK_TRACE_HERE_FOR_MALLOC; 217e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard return asan_realloc(ptr, size, &stack); 218e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } else { 219e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard // We can't recover from reallocating an unknown address, because 220e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard // this would require reading at most |size| bytes from 221e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard // potentially unaccessible memory. 222e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard AsanPrintf("cf_realloc(%p) -- attempting to realloc unallocated memory.\n" 223e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard "This is an unrecoverable problem, exiting now.\n", 224e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ptr); 225e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard print_zone_for_ptr(ptr); 226b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard GET_STACK_TRACE_HERE_FOR_FREE(ptr); 227e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard stack.PrintStack(); 228e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ShowStatsAndAbort(); 229e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard return 0; // unreachable 230e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } 231e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } 232e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard} 233e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 234b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgardvoid mz_destroy(malloc_zone_t* zone) { 235e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard // A no-op -- we will not be destroyed! 236e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard AsanPrintf("mz_destroy() called -- ignoring\n"); 237e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard} 238e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard // from AvailabilityMacros.h 239e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#if defined(MAC_OS_X_VERSION_10_6) && \ 240e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 241e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardvoid *mz_memalign(malloc_zone_t *zone, size_t align, size_t size) { 242e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard if (!asan_inited) { 243e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard CHECK(system_malloc_zone); 244e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard return malloc_zone_memalign(system_malloc_zone, align, size); 245e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } 246e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard GET_STACK_TRACE_HERE_FOR_MALLOC; 247e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard return asan_memalign(align, size, &stack); 248e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard} 249e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 250e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard// This function is currently unused, and we build with -Werror. 251e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#if 0 252e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardvoid mz_free_definite_size(malloc_zone_t* zone, void *ptr, size_t size) { 253e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard // TODO(glider): check that |size| is valid. 254e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard UNIMPLEMENTED(); 255e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard} 256e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#endif 257e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#endif 258e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 259e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard// malloc_introspection callbacks. I'm not clear on what all of these do. 260e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardkern_return_t mi_enumerator(task_t task, void *, 261e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard unsigned type_mask, vm_address_t zone_address, 262e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard memory_reader_t reader, 263e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard vm_range_recorder_t recorder) { 264e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard // Should enumerate all the pointers we have. Seems like a lot of work. 265e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard return KERN_FAILURE; 266e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard} 267e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 268e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardsize_t mi_good_size(malloc_zone_t *zone, size_t size) { 269e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard // I think it's always safe to return size, but we maybe could do better. 270e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard return size; 271e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard} 272e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 273956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongboolean_t mi_check(malloc_zone_t *zone) { 274956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong UNIMPLEMENTED(); 275956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return true; 276956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 277956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 278e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardvoid mi_print(malloc_zone_t *zone, boolean_t verbose) { 279e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard UNIMPLEMENTED(); 280e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard return; 281e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard} 282e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 283e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardvoid mi_log(malloc_zone_t *zone, void *address) { 284e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard // I don't think we support anything like this 285b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard} 286e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 287e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardvoid mi_force_lock(malloc_zone_t *zone) { 288e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard asan_mz_force_lock(); 289e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard} 290b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 291b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgardvoid mi_force_unlock(malloc_zone_t *zone) { 292b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard asan_mz_force_unlock(); 293b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard} 294e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 295e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard// This function is currently unused, and we build with -Werror. 296e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#if 0 297e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardvoid mi_statistics(malloc_zone_t *zone, malloc_statistics_t *stats) { 298e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard // TODO(csilvers): figure out how to fill these out 299b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard // TODO(glider): port this from tcmalloc when ready. 300e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard stats->blocks_in_use = 0; 301b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard stats->size_in_use = 0; 302b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard stats->max_size_in_use = 0; 303b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard stats->size_allocated = 0; 304e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard} 305e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#endif 306e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 307e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#if defined(MAC_OS_X_VERSION_10_6) && \ 308956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 309956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongboolean_t mi_zone_locked(malloc_zone_t *zone) { 310956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong // UNIMPLEMENTED(); 311956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return false; 312956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 313e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#endif 314e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 315e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard} // unnamed namespace 316e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 317e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardextern bool kCFUseCollectableAllocator; // is GC on? 318e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 319e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardnamespace __asan { 320e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardvoid ReplaceSystemMalloc() { 321e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard static malloc_introspection_t asan_introspection; 322b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard // Ok to use internal_memset, these places are not performance-critical. 323e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard internal_memset(&asan_introspection, 0, sizeof(asan_introspection)); 324e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 325b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard asan_introspection.enumerator = &mi_enumerator; 326b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard asan_introspection.good_size = &mi_good_size; 327b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard asan_introspection.check = &mi_check; 328e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard asan_introspection.print = &mi_print; 329e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard asan_introspection.log = &mi_log; 330e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard asan_introspection.force_lock = &mi_force_lock; 331e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard asan_introspection.force_unlock = &mi_force_unlock; 332e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 333e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard static malloc_zone_t asan_zone; 334e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard internal_memset(&asan_zone, 0, sizeof(malloc_zone_t)); 335e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 336b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard // Start with a version 4 zone which is used for OS X 10.4 and 10.5. 337b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard asan_zone.version = 4; 338e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard asan_zone.zone_name = "asan"; 339b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard asan_zone.size = &mz_size; 340e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard asan_zone.malloc = &mz_malloc; 341e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard asan_zone.calloc = &mz_calloc; 3428a3b3707a6e320ba75f4ecd47fdc001f16c15cb8Martin Storsjo asan_zone.valloc = &mz_valloc; 3438a3b3707a6e320ba75f4ecd47fdc001f16c15cb8Martin Storsjo asan_zone.free = &mz_free; 3448a3b3707a6e320ba75f4ecd47fdc001f16c15cb8Martin Storsjo asan_zone.realloc = &mz_realloc; 3458a3b3707a6e320ba75f4ecd47fdc001f16c15cb8Martin Storsjo asan_zone.destroy = &mz_destroy; 3468a3b3707a6e320ba75f4ecd47fdc001f16c15cb8Martin Storsjo asan_zone.batch_malloc = 0; 3478a3b3707a6e320ba75f4ecd47fdc001f16c15cb8Martin Storsjo asan_zone.batch_free = 0; 348e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard asan_zone.introspect = &asan_introspection; 349e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 350e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard // from AvailabilityMacros.h 351956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#if defined(MAC_OS_X_VERSION_10_6) && \ 352956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 353956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong // Switch to version 6 on OSX 10.6 to support memalign. 354956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong asan_zone.version = 6; 355956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong asan_zone.free_definite_size = 0; 356e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard asan_zone.memalign = &mz_memalign; 357e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard asan_introspection.zone_locked = &mi_zone_locked; 358e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 359e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard // Request the default purgable zone to force its creation. The 360e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard // current default zone is registered with the purgable zone for 361e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard // doing tiny and small allocs. Sadly, it assumes that the default 362b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard // zone is the szone implementation from OS X and will crash if it 363e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard // isn't. By creating the zone now, this will be true and changing 364e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard // the default zone won't cause a problem. (OS X 10.6 and higher.) 365b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard system_purgeable_zone = malloc_default_purgeable_zone(); 366e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#endif 367e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 368e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard // Register the ASan zone. At this point, it will not be the 369956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong // default zone. 370956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong malloc_zone_register(&asan_zone); 371956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 372b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard // Unregister and reregister the default zone. Unregistering swaps 373956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong // the specified zone with the last one registered which for the 374e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard // default zone makes the more recently registered zone the default 375e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard // zone. The default zone is then re-registered to ensure that 376e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard // allocations made from it earlier will be handled correctly. 377e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard // Things are not guaranteed to work that way, but it's how they work now. 378e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard system_malloc_zone = malloc_default_zone(); 379e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard malloc_zone_unregister(system_malloc_zone); 380b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard malloc_zone_register(system_malloc_zone); 381b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard // Make sure the default allocator was replaced. 382e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard CHECK(malloc_default_zone() == &asan_zone); 383b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 384e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard if (FLAG_replace_cfallocator) { 385956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong static CFAllocatorContext asan_context = 386956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong { /*version*/ 0, /*info*/ &asan_zone, 387956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /*retain*/ 0, /*release*/ 0, 388956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /*copyDescription*/0, 389956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /*allocate*/ &cf_malloc, 390956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /*reallocate*/ &cf_realloc, 391b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard /*deallocate*/ &cf_free, 392956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong /*preferredSize*/ 0 }; 393956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong cf_asan = CFAllocatorCreate(kCFAllocatorUseContext, &asan_context); 394956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong CFAllocatorSetDefault(cf_asan); 395956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 396956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 397956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} // namespace __asan 398956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 399956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#endif // __APPLE__ 400956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong