179fc3c042bbe8348fb6f3bff7a5575e4425e5a38Alexander Potapenko//===-- asan_malloc_mac.cc ------------------------------------------------===// 21e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 31e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// The LLVM Compiler Infrastructure 41e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 51e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// This file is distributed under the University of Illinois Open Source 61e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// License. See LICENSE.TXT for details. 71e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 81e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===----------------------------------------------------------------------===// 91e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// This file is a part of AddressSanitizer, an address sanity checker. 111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Mac-specific malloc interception. 131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===----------------------------------------------------------------------===// 141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 15d6567c5166412f6acdde851e767c26f332d51d3dKostya Serebryany#ifdef __APPLE__ 16d6567c5166412f6acdde851e767c26f332d51d3dKostya Serebryany 171e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include <AvailabilityMacros.h> 181e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include <CoreFoundation/CFBase.h> 19d079db6dfbf3b0ec5fa1cc8d093e0dae6f970bf8Alexander Potapenko#include <dlfcn.h> 201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include <malloc/malloc.h> 211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_allocator.h" 231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_interceptors.h" 241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_internal.h" 25d079db6dfbf3b0ec5fa1cc8d093e0dae6f970bf8Alexander Potapenko#include "asan_mac.h" 26663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov#include "asan_report.h" 271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_stack.h" 281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 291e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Similar code is used in Google Perftools, 301e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// http://code.google.com/p/google-perftools. 311e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 321e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// ---------------------- Replacement functions ---------------- {{{1 331e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyusing namespace __asan; // NOLINT 341e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 35e205a9daec9ec4afed956cf5455889725b9192fbAlexander Potapenko// TODO(glider): do we need both zones? 36e205a9daec9ec4afed956cf5455889725b9192fbAlexander Potapenkostatic malloc_zone_t *system_malloc_zone = 0; 37e205a9daec9ec4afed956cf5455889725b9192fbAlexander Potapenkostatic malloc_zone_t *system_purgeable_zone = 0; 3823a3b760646aab699d29896d4feaf2fc84ec3955Alexander Potapenkostatic malloc_zone_t asan_zone; 39e205a9daec9ec4afed956cf5455889725b9192fbAlexander PotapenkoCFAllocatorRef cf_asan = 0; 40e205a9daec9ec4afed956cf5455889725b9192fbAlexander Potapenko 412122f705fcad0316b5ff9d5e1e9260fd18191e1fAlexander Potapenko// _CFRuntimeCreateInstance() checks whether the supplied allocator is 422122f705fcad0316b5ff9d5e1e9260fd18191e1fAlexander Potapenko// kCFAllocatorSystemDefault and, if it is not, stores the allocator reference 432122f705fcad0316b5ff9d5e1e9260fd18191e1fAlexander Potapenko// at the beginning of the allocated memory and returns the pointer to the 442122f705fcad0316b5ff9d5e1e9260fd18191e1fAlexander Potapenko// allocated memory plus sizeof(CFAllocatorRef). See 452122f705fcad0316b5ff9d5e1e9260fd18191e1fAlexander Potapenko// http://www.opensource.apple.com/source/CF/CF-635.21/CFRuntime.c 462122f705fcad0316b5ff9d5e1e9260fd18191e1fAlexander Potapenko// Pointers returned by _CFRuntimeCreateInstance() can then be passed directly 472122f705fcad0316b5ff9d5e1e9260fd18191e1fAlexander Potapenko// to free() or CFAllocatorDeallocate(), which leads to false invalid free 482122f705fcad0316b5ff9d5e1e9260fd18191e1fAlexander Potapenko// reports. 492122f705fcad0316b5ff9d5e1e9260fd18191e1fAlexander Potapenko// The corresponding rdar bug is http://openradar.appspot.com/radar?id=1796404. 502122f705fcad0316b5ff9d5e1e9260fd18191e1fAlexander Potapenkovoid* ALWAYS_INLINE get_saved_cfallocator_ref(void *ptr) { 512122f705fcad0316b5ff9d5e1e9260fd18191e1fAlexander Potapenko if (flags()->replace_cfallocator) { 522122f705fcad0316b5ff9d5e1e9260fd18191e1fAlexander Potapenko // Make sure we're not hitting the previous page. This may be incorrect 532122f705fcad0316b5ff9d5e1e9260fd18191e1fAlexander Potapenko // if ASan's malloc returns an address ending with 0xFF8, which will be 542122f705fcad0316b5ff9d5e1e9260fd18191e1fAlexander Potapenko // then padded to a page boundary with a CFAllocatorRef. 552122f705fcad0316b5ff9d5e1e9260fd18191e1fAlexander Potapenko uptr arith_ptr = (uptr)ptr; 562122f705fcad0316b5ff9d5e1e9260fd18191e1fAlexander Potapenko if ((arith_ptr & 0xFFF) > sizeof(CFAllocatorRef)) { 572122f705fcad0316b5ff9d5e1e9260fd18191e1fAlexander Potapenko CFAllocatorRef *saved = 582122f705fcad0316b5ff9d5e1e9260fd18191e1fAlexander Potapenko (CFAllocatorRef*)(arith_ptr - sizeof(CFAllocatorRef)); 592122f705fcad0316b5ff9d5e1e9260fd18191e1fAlexander Potapenko if ((*saved == cf_asan) && asan_mz_size(saved)) ptr = (void*)saved; 602122f705fcad0316b5ff9d5e1e9260fd18191e1fAlexander Potapenko } 612122f705fcad0316b5ff9d5e1e9260fd18191e1fAlexander Potapenko } 622122f705fcad0316b5ff9d5e1e9260fd18191e1fAlexander Potapenko return ptr; 632122f705fcad0316b5ff9d5e1e9260fd18191e1fAlexander Potapenko} 642122f705fcad0316b5ff9d5e1e9260fd18191e1fAlexander Potapenko 651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// The free() implementation provided by OS X calls malloc_zone_from_ptr() 663f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany// to find the owner of |ptr|. If the result is 0, an invalid free() is 671e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// reported. Our implementation falls back to asan_free() in this case 681e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// in order to print an ASan-style report. 69e205a9daec9ec4afed956cf5455889725b9192fbAlexander Potapenko// 70e205a9daec9ec4afed956cf5455889725b9192fbAlexander Potapenko// For the objects created by _CFRuntimeCreateInstance a CFAllocatorRef is 71e205a9daec9ec4afed956cf5455889725b9192fbAlexander Potapenko// placed at the beginning of the allocated chunk and the pointer returned by 72e205a9daec9ec4afed956cf5455889725b9192fbAlexander Potapenko// our allocator is off by sizeof(CFAllocatorRef). This pointer can be then 73e205a9daec9ec4afed956cf5455889725b9192fbAlexander Potapenko// passed directly to free(), which will lead to errors. 74e205a9daec9ec4afed956cf5455889725b9192fbAlexander Potapenko// To overcome this we're checking whether |ptr-sizeof(CFAllocatorRef)| 75e205a9daec9ec4afed956cf5455889725b9192fbAlexander Potapenko// contains a pointer to our CFAllocator (assuming no other allocator is used). 76e205a9daec9ec4afed956cf5455889725b9192fbAlexander Potapenko// See http://code.google.com/p/address-sanitizer/issues/detail?id=70 for more 77e205a9daec9ec4afed956cf5455889725b9192fbAlexander Potapenko// info. 78e205a9daec9ec4afed956cf5455889725b9192fbAlexander PotapenkoINTERCEPTOR(void, free, void *ptr) { 791e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany malloc_zone_t *zone = malloc_zone_from_ptr(ptr); 801e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (zone) { 811e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#if defined(MAC_OS_X_VERSION_10_6) && \ 821e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 831e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if ((zone->version >= 6) && (zone->free_definite_size)) { 841e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany zone->free_definite_size(zone, ptr, malloc_size(ptr)); 851e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } else { 861e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany malloc_zone_free(zone, ptr); 871e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 881e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#else 891e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany malloc_zone_free(zone, ptr); 901e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#endif 911e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } else { 922122f705fcad0316b5ff9d5e1e9260fd18191e1fAlexander Potapenko if (!asan_mz_size(ptr)) ptr = get_saved_cfallocator_ref(ptr); 931e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE_FOR_FREE(ptr); 941e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_free(ptr, &stack); 951e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 961e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 971e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 9823a3b760646aab699d29896d4feaf2fc84ec3955Alexander Potapenkonamespace __asan { 9923a3b760646aab699d29896d4feaf2fc84ec3955Alexander Potapenko void ReplaceCFAllocator(); 10023a3b760646aab699d29896d4feaf2fc84ec3955Alexander Potapenko} 10123a3b760646aab699d29896d4feaf2fc84ec3955Alexander Potapenko 102decaec9ee3177b5e81e358ad8e93ab70b38a1cc0Alexander Potapenko// We can't always replace the default CFAllocator with cf_asan right in 103decaec9ee3177b5e81e358ad8e93ab70b38a1cc0Alexander Potapenko// ReplaceSystemMalloc(), because it is sometimes called before 104decaec9ee3177b5e81e358ad8e93ab70b38a1cc0Alexander Potapenko// __CFInitialize(), when the default allocator is invalid and replacing it may 105decaec9ee3177b5e81e358ad8e93ab70b38a1cc0Alexander Potapenko// crash the program. Instead we wait for the allocator to initialize and jump 106decaec9ee3177b5e81e358ad8e93ab70b38a1cc0Alexander Potapenko// in just after __CFInitialize(). Nobody is going to allocate memory using 107decaec9ee3177b5e81e358ad8e93ab70b38a1cc0Alexander Potapenko// CFAllocators before that, so we won't miss anything. 108decaec9ee3177b5e81e358ad8e93ab70b38a1cc0Alexander Potapenko// 109decaec9ee3177b5e81e358ad8e93ab70b38a1cc0Alexander Potapenko// See http://code.google.com/p/address-sanitizer/issues/detail?id=87 110decaec9ee3177b5e81e358ad8e93ab70b38a1cc0Alexander Potapenko// and http://opensource.apple.com/source/CF/CF-550.43/CFRuntime.c 111decaec9ee3177b5e81e358ad8e93ab70b38a1cc0Alexander PotapenkoINTERCEPTOR(void, __CFInitialize) { 1120ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko // If the runtime is built as dynamic library, __CFInitialize wrapper may be 1130ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko // called before __asan_init. 1140ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko#if !MAC_INTERPOSE_FUNCTIONS 115cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov CHECK(flags()->replace_cfallocator); 11623a3b760646aab699d29896d4feaf2fc84ec3955Alexander Potapenko CHECK(asan_inited); 1170ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko#endif 118decaec9ee3177b5e81e358ad8e93ab70b38a1cc0Alexander Potapenko REAL(__CFInitialize)(); 1190ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko if (!cf_asan && asan_inited) ReplaceCFAllocator(); 120decaec9ee3177b5e81e358ad8e93ab70b38a1cc0Alexander Potapenko} 121decaec9ee3177b5e81e358ad8e93ab70b38a1cc0Alexander Potapenko 1221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanynamespace { 12323a3b760646aab699d29896d4feaf2fc84ec3955Alexander Potapenko 1241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// TODO(glider): the mz_* functions should be united with the Linux wrappers, 1251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// as they are basically copied from there. 1261e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanysize_t mz_size(malloc_zone_t* zone, const void* ptr) { 1274fd95f141f78906570c15a8a3b4cf0a7b50a201dAlexey Samsonov return asan_mz_size(ptr); 1281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 1291e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 1301e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid *mz_malloc(malloc_zone_t *zone, size_t size) { 1311e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (!asan_inited) { 1321e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany CHECK(system_malloc_zone); 1331e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return malloc_zone_malloc(system_malloc_zone, size); 1341e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 1351e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE_FOR_MALLOC; 1361e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return asan_malloc(size, &stack); 1371e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 1381e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 1391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid *cf_malloc(CFIndex size, CFOptionFlags hint, void *info) { 1401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (!asan_inited) { 1411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany CHECK(system_malloc_zone); 1421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return malloc_zone_malloc(system_malloc_zone, size); 1431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 1441e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE_FOR_MALLOC; 1451e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return asan_malloc(size, &stack); 1461e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 1471e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 1481e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid *mz_calloc(malloc_zone_t *zone, size_t nmemb, size_t size) { 1491e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (!asan_inited) { 15009672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym. 1511e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany const size_t kCallocPoolSize = 1024; 1523f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany static uptr calloc_memory_for_dlsym[kCallocPoolSize]; 1531e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany static size_t allocated; 1541e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany size_t size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize; 1551e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany void *mem = (void*)&calloc_memory_for_dlsym[allocated]; 1561e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany allocated += size_in_words; 1571e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany CHECK(allocated < kCallocPoolSize); 1581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return mem; 1591e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 1601e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE_FOR_MALLOC; 1611e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return asan_calloc(nmemb, size, &stack); 1621e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 1631e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 1641e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid *mz_valloc(malloc_zone_t *zone, size_t size) { 1651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (!asan_inited) { 1661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany CHECK(system_malloc_zone); 1671e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return malloc_zone_valloc(system_malloc_zone, size); 1681e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 1691e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE_FOR_MALLOC; 1701e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return asan_memalign(kPageSize, size, &stack); 1711e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 1721e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 173663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov#define GET_ZONE_FOR_PTR(ptr) \ 174663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov malloc_zone_t *zone_ptr = malloc_zone_from_ptr(ptr); \ 175663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov const char *zone_name = (zone_ptr == 0) ? 0 : zone_ptr->zone_name 1761e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 1770aa794d78fbb6359f81025217559f1b03ff07999Alexander Potapenkovoid ALWAYS_INLINE free_common(void *context, void *ptr) { 1781e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (!ptr) return; 1792122f705fcad0316b5ff9d5e1e9260fd18191e1fAlexander Potapenko if (asan_mz_size(ptr)) { 1801e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE_FOR_FREE(ptr); 1812122f705fcad0316b5ff9d5e1e9260fd18191e1fAlexander Potapenko asan_free(ptr, &stack); 1822122f705fcad0316b5ff9d5e1e9260fd18191e1fAlexander Potapenko } else { 1832122f705fcad0316b5ff9d5e1e9260fd18191e1fAlexander Potapenko // If the pointer does not belong to any of the zones, use one of the 1842122f705fcad0316b5ff9d5e1e9260fd18191e1fAlexander Potapenko // fallback methods to free memory. 185d262653fa207c6ee89700f192c5ff809a8ed6f52Alexander Potapenko malloc_zone_t *zone_ptr = malloc_zone_from_ptr(ptr); 186d262653fa207c6ee89700f192c5ff809a8ed6f52Alexander Potapenko if (zone_ptr == system_purgeable_zone) { 1872122f705fcad0316b5ff9d5e1e9260fd18191e1fAlexander Potapenko // allocations from malloc_default_purgeable_zone() done before 188d262653fa207c6ee89700f192c5ff809a8ed6f52Alexander Potapenko // __asan_init() may be occasionally freed via free_common(). 1892122f705fcad0316b5ff9d5e1e9260fd18191e1fAlexander Potapenko // see http://code.google.com/p/address-sanitizer/issues/detail?id=99. 190d262653fa207c6ee89700f192c5ff809a8ed6f52Alexander Potapenko malloc_zone_free(zone_ptr, ptr); 191d262653fa207c6ee89700f192c5ff809a8ed6f52Alexander Potapenko } else { 1922122f705fcad0316b5ff9d5e1e9260fd18191e1fAlexander Potapenko // If the memory chunk pointer was moved to store additional 1932122f705fcad0316b5ff9d5e1e9260fd18191e1fAlexander Potapenko // CFAllocatorRef, fix it back. 1942122f705fcad0316b5ff9d5e1e9260fd18191e1fAlexander Potapenko ptr = get_saved_cfallocator_ref(ptr); 1952122f705fcad0316b5ff9d5e1e9260fd18191e1fAlexander Potapenko GET_STACK_TRACE_HERE_FOR_FREE(ptr); 1962122f705fcad0316b5ff9d5e1e9260fd18191e1fAlexander Potapenko if (!flags()->mac_ignore_invalid_free) { 1972122f705fcad0316b5ff9d5e1e9260fd18191e1fAlexander Potapenko asan_free(ptr, &stack); 1982122f705fcad0316b5ff9d5e1e9260fd18191e1fAlexander Potapenko } else { 1992122f705fcad0316b5ff9d5e1e9260fd18191e1fAlexander Potapenko GET_ZONE_FOR_PTR(ptr); 2002122f705fcad0316b5ff9d5e1e9260fd18191e1fAlexander Potapenko WarnMacFreeUnallocated((uptr)ptr, (uptr)zone_ptr, zone_name, &stack); 2012122f705fcad0316b5ff9d5e1e9260fd18191e1fAlexander Potapenko return; 2022122f705fcad0316b5ff9d5e1e9260fd18191e1fAlexander Potapenko } 203d262653fa207c6ee89700f192c5ff809a8ed6f52Alexander Potapenko } 2041e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 2051e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 2061e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 2070aa794d78fbb6359f81025217559f1b03ff07999Alexander Potapenko// TODO(glider): the allocation callbacks need to be refactored. 2080aa794d78fbb6359f81025217559f1b03ff07999Alexander Potapenkovoid mz_free(malloc_zone_t *zone, void *ptr) { 2090aa794d78fbb6359f81025217559f1b03ff07999Alexander Potapenko free_common(zone, ptr); 2100aa794d78fbb6359f81025217559f1b03ff07999Alexander Potapenko} 2110aa794d78fbb6359f81025217559f1b03ff07999Alexander Potapenko 2121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid cf_free(void *ptr, void *info) { 2130aa794d78fbb6359f81025217559f1b03ff07999Alexander Potapenko free_common(info, ptr); 2141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 2151e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 2161e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid *mz_realloc(malloc_zone_t *zone, void *ptr, size_t size) { 2171e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (!ptr) { 2181e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE_FOR_MALLOC; 2191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return asan_malloc(size, &stack); 2201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } else { 2214fd95f141f78906570c15a8a3b4cf0a7b50a201dAlexey Samsonov if (asan_mz_size(ptr)) { 2221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE_FOR_MALLOC; 2231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return asan_realloc(ptr, size, &stack); 2241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } else { 2251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // We can't recover from reallocating an unknown address, because 2261e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // this would require reading at most |size| bytes from 2271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // potentially unaccessible memory. 2281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE_FOR_FREE(ptr); 229663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov GET_ZONE_FOR_PTR(ptr); 230663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov ReportMacMzReallocUnknown((uptr)ptr, (uptr)zone_ptr, zone_name, &stack); 2311e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 2321e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 2331e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 2341e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 2351e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid *cf_realloc(void *ptr, CFIndex size, CFOptionFlags hint, void *info) { 2361e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (!ptr) { 2371e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE_FOR_MALLOC; 2381e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return asan_malloc(size, &stack); 2391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } else { 2404fd95f141f78906570c15a8a3b4cf0a7b50a201dAlexey Samsonov if (asan_mz_size(ptr)) { 2411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE_FOR_MALLOC; 2421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return asan_realloc(ptr, size, &stack); 2431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } else { 2441e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // We can't recover from reallocating an unknown address, because 2451e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // this would require reading at most |size| bytes from 2461e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // potentially unaccessible memory. 2471e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE_FOR_FREE(ptr); 248663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov GET_ZONE_FOR_PTR(ptr); 249663c50134e01feefb6c5418c6ec7753be951c14fAlexey Samsonov ReportMacCfReallocUnknown((uptr)ptr, (uptr)zone_ptr, zone_name, &stack); 2501e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 2511e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 2521e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 2531e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 2541e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid mz_destroy(malloc_zone_t* zone) { 2551e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // A no-op -- we will not be destroyed! 256283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany Printf("mz_destroy() called -- ignoring\n"); 2571e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 2581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // from AvailabilityMacros.h 2591e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#if defined(MAC_OS_X_VERSION_10_6) && \ 2601e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 2611e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid *mz_memalign(malloc_zone_t *zone, size_t align, size_t size) { 2621e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (!asan_inited) { 2631e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany CHECK(system_malloc_zone); 2641e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return malloc_zone_memalign(system_malloc_zone, align, size); 2651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 2661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE_FOR_MALLOC; 2671e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return asan_memalign(align, size, &stack); 2681e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 2691e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 270c1ef2a0b8022f200f8bbb36641df866c4369876dDaniel Dunbar// This function is currently unused, and we build with -Werror. 271c1ef2a0b8022f200f8bbb36641df866c4369876dDaniel Dunbar#if 0 2721e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid mz_free_definite_size(malloc_zone_t* zone, void *ptr, size_t size) { 2731e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // TODO(glider): check that |size| is valid. 2741e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany UNIMPLEMENTED(); 2751e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 2761e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#endif 277c1ef2a0b8022f200f8bbb36641df866c4369876dDaniel Dunbar#endif 2781e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 2791e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// malloc_introspection callbacks. I'm not clear on what all of these do. 2801e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanykern_return_t mi_enumerator(task_t task, void *, 2811e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany unsigned type_mask, vm_address_t zone_address, 2821e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany memory_reader_t reader, 2831e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany vm_range_recorder_t recorder) { 2841e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // Should enumerate all the pointers we have. Seems like a lot of work. 2851e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return KERN_FAILURE; 2861e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 2871e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 2881e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanysize_t mi_good_size(malloc_zone_t *zone, size_t size) { 2891e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // I think it's always safe to return size, but we maybe could do better. 2901e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return size; 2911e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 2921e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 2931e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyboolean_t mi_check(malloc_zone_t *zone) { 2941e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany UNIMPLEMENTED(); 2951e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return true; 2961e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 2971e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 2981e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid mi_print(malloc_zone_t *zone, boolean_t verbose) { 2991e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany UNIMPLEMENTED(); 3001e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return; 3011e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 3021e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3031e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid mi_log(malloc_zone_t *zone, void *address) { 3041e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // I don't think we support anything like this 3051e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 3061e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3071e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid mi_force_lock(malloc_zone_t *zone) { 3084fd95f141f78906570c15a8a3b4cf0a7b50a201dAlexey Samsonov asan_mz_force_lock(); 3091e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 3101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid mi_force_unlock(malloc_zone_t *zone) { 3124fd95f141f78906570c15a8a3b4cf0a7b50a201dAlexey Samsonov asan_mz_force_unlock(); 3131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 3141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 315c1ef2a0b8022f200f8bbb36641df866c4369876dDaniel Dunbar// This function is currently unused, and we build with -Werror. 316c1ef2a0b8022f200f8bbb36641df866c4369876dDaniel Dunbar#if 0 3171e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid mi_statistics(malloc_zone_t *zone, malloc_statistics_t *stats) { 3181e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // TODO(csilvers): figure out how to fill these out 3191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // TODO(glider): port this from tcmalloc when ready. 3201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany stats->blocks_in_use = 0; 3211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany stats->size_in_use = 0; 3221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany stats->max_size_in_use = 0; 3231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany stats->size_allocated = 0; 3241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 325c1ef2a0b8022f200f8bbb36641df866c4369876dDaniel Dunbar#endif 3261e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 327eeb719154538f38ffd54d8d3bfd8e113b97fe6a1Eli Friedman#if defined(MAC_OS_X_VERSION_10_6) && \ 328eeb719154538f38ffd54d8d3bfd8e113b97fe6a1Eli Friedman MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 3291e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyboolean_t mi_zone_locked(malloc_zone_t *zone) { 3301e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // UNIMPLEMENTED(); 3311e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return false; 3321e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 333eeb719154538f38ffd54d8d3bfd8e113b97fe6a1Eli Friedman#endif 3341e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3351e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} // unnamed namespace 3361e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 337decaec9ee3177b5e81e358ad8e93ab70b38a1cc0Alexander Potapenkoextern int __CFRuntimeClassTableSize; 3381e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanynamespace __asan { 34023a3b760646aab699d29896d4feaf2fc84ec3955Alexander Potapenkovoid ReplaceCFAllocator() { 34123a3b760646aab699d29896d4feaf2fc84ec3955Alexander Potapenko static CFAllocatorContext asan_context = { 34223a3b760646aab699d29896d4feaf2fc84ec3955Alexander Potapenko /*version*/ 0, /*info*/ &asan_zone, 34323a3b760646aab699d29896d4feaf2fc84ec3955Alexander Potapenko /*retain*/ 0, /*release*/ 0, 34423a3b760646aab699d29896d4feaf2fc84ec3955Alexander Potapenko /*copyDescription*/0, 34523a3b760646aab699d29896d4feaf2fc84ec3955Alexander Potapenko /*allocate*/ &cf_malloc, 34623a3b760646aab699d29896d4feaf2fc84ec3955Alexander Potapenko /*reallocate*/ &cf_realloc, 34723a3b760646aab699d29896d4feaf2fc84ec3955Alexander Potapenko /*deallocate*/ &cf_free, 34823a3b760646aab699d29896d4feaf2fc84ec3955Alexander Potapenko /*preferredSize*/ 0 }; 34975b19ebf25af204cf209d108997272822241d6daAlexander Potapenko if (!cf_asan) 35075b19ebf25af204cf209d108997272822241d6daAlexander Potapenko cf_asan = CFAllocatorCreate(kCFAllocatorUseContext, &asan_context); 35175b19ebf25af204cf209d108997272822241d6daAlexander Potapenko if (CFAllocatorGetDefault() != cf_asan) 35275b19ebf25af204cf209d108997272822241d6daAlexander Potapenko CFAllocatorSetDefault(cf_asan); 35323a3b760646aab699d29896d4feaf2fc84ec3955Alexander Potapenko} 35423a3b760646aab699d29896d4feaf2fc84ec3955Alexander Potapenko 3551e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid ReplaceSystemMalloc() { 3561e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany static malloc_introspection_t asan_introspection; 357ebb9702cff96192c6a6ea963037929ca7ed60eaeAlexander Potapenko // Ok to use internal_memset, these places are not performance-critical. 358ebb9702cff96192c6a6ea963037929ca7ed60eaeAlexander Potapenko internal_memset(&asan_introspection, 0, sizeof(asan_introspection)); 3591e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3601e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_introspection.enumerator = &mi_enumerator; 3611e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_introspection.good_size = &mi_good_size; 3621e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_introspection.check = &mi_check; 3631e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_introspection.print = &mi_print; 3641e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_introspection.log = &mi_log; 3651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_introspection.force_lock = &mi_force_lock; 3661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_introspection.force_unlock = &mi_force_unlock; 3671e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 368ebb9702cff96192c6a6ea963037929ca7ed60eaeAlexander Potapenko internal_memset(&asan_zone, 0, sizeof(malloc_zone_t)); 3691e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3701e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // Start with a version 4 zone which is used for OS X 10.4 and 10.5. 3711e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_zone.version = 4; 3721e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_zone.zone_name = "asan"; 3731e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_zone.size = &mz_size; 3741e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_zone.malloc = &mz_malloc; 3751e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_zone.calloc = &mz_calloc; 3761e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_zone.valloc = &mz_valloc; 3771e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_zone.free = &mz_free; 3781e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_zone.realloc = &mz_realloc; 3791e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_zone.destroy = &mz_destroy; 3803f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany asan_zone.batch_malloc = 0; 3813f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany asan_zone.batch_free = 0; 3821e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_zone.introspect = &asan_introspection; 3831e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3841e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // from AvailabilityMacros.h 3851e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#if defined(MAC_OS_X_VERSION_10_6) && \ 3861e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 3871e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // Switch to version 6 on OSX 10.6 to support memalign. 3881e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_zone.version = 6; 3891e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_zone.free_definite_size = 0; 3901e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_zone.memalign = &mz_memalign; 3911e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_introspection.zone_locked = &mi_zone_locked; 3921e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3931e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // Request the default purgable zone to force its creation. The 3941e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // current default zone is registered with the purgable zone for 3951e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // doing tiny and small allocs. Sadly, it assumes that the default 3961e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // zone is the szone implementation from OS X and will crash if it 3971e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // isn't. By creating the zone now, this will be true and changing 3981e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // the default zone won't cause a problem. (OS X 10.6 and higher.) 3991e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany system_purgeable_zone = malloc_default_purgeable_zone(); 4001e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#endif 4011e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 4021e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // Register the ASan zone. At this point, it will not be the 4031e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // default zone. 4041e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany malloc_zone_register(&asan_zone); 4051e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 4061e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // Unregister and reregister the default zone. Unregistering swaps 4071e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // the specified zone with the last one registered which for the 4081e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // default zone makes the more recently registered zone the default 4091e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // zone. The default zone is then re-registered to ensure that 4101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // allocations made from it earlier will be handled correctly. 4111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // Things are not guaranteed to work that way, but it's how they work now. 4121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany system_malloc_zone = malloc_default_zone(); 4131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany malloc_zone_unregister(system_malloc_zone); 4141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany malloc_zone_register(system_malloc_zone); 4151e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // Make sure the default allocator was replaced. 4161e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany CHECK(malloc_default_zone() == &asan_zone); 4171e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 418cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (flags()->replace_cfallocator) { 41923a3b760646aab699d29896d4feaf2fc84ec3955Alexander Potapenko // If __CFInitialize() hasn't been called yet, cf_asan will be created and 42023a3b760646aab699d29896d4feaf2fc84ec3955Alexander Potapenko // installed as the default allocator after __CFInitialize() finishes (see 42123a3b760646aab699d29896d4feaf2fc84ec3955Alexander Potapenko // the interceptor for __CFInitialize() above). Otherwise install cf_asan 42223a3b760646aab699d29896d4feaf2fc84ec3955Alexander Potapenko // right now. On both Snow Leopard and Lion __CFInitialize() calls 423bf9f6fbf015f687784e26f26570924be4ca3924fAlexander Potapenko // __CFAllocatorInitialize(), which initializes the _base._cfisa field of 424bf9f6fbf015f687784e26f26570924be4ca3924fAlexander Potapenko // the default allocators we check here. 425bf9f6fbf015f687784e26f26570924be4ca3924fAlexander Potapenko if (((CFRuntimeBase*)kCFAllocatorSystemDefault)->_cfisa) { 42623a3b760646aab699d29896d4feaf2fc84ec3955Alexander Potapenko ReplaceCFAllocator(); 427d079db6dfbf3b0ec5fa1cc8d093e0dae6f970bf8Alexander Potapenko } 4281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 4291e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 4301e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} // namespace __asan 431d6567c5166412f6acdde851e767c26f332d51d3dKostya Serebryany 432d6567c5166412f6acdde851e767c26f332d51d3dKostya Serebryany#endif // __APPLE__ 433