asan_malloc_mac.cc revision e5f5895bda30f374b0b51412fd4d837fa59aed66
1e5f5895bda30f374b0b51412fd4d837fa59aed66Alexey Samsonov//===-- asan_rtl.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> 191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include <malloc/malloc.h> 201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include <setjmp.h> 211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_allocator.h" 231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_interceptors.h" 241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_internal.h" 251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_stack.h" 261e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Similar code is used in Google Perftools, 281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// http://code.google.com/p/google-perftools. 291e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 301e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// ---------------------- Replacement functions ---------------- {{{1 311e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyusing namespace __asan; // NOLINT 321e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 331e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// The free() implementation provided by OS X calls malloc_zone_from_ptr() 343f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany// to find the owner of |ptr|. If the result is 0, an invalid free() is 351e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// reported. Our implementation falls back to asan_free() in this case 361e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// in order to print an ASan-style report. 371e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyextern "C" 381e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid free(void *ptr) { 391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany malloc_zone_t *zone = malloc_zone_from_ptr(ptr); 401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (zone) { 411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#if defined(MAC_OS_X_VERSION_10_6) && \ 421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if ((zone->version >= 6) && (zone->free_definite_size)) { 441e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany zone->free_definite_size(zone, ptr, malloc_size(ptr)); 451e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } else { 461e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany malloc_zone_free(zone, ptr); 471e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 481e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#else 491e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany malloc_zone_free(zone, ptr); 501e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#endif 511e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } else { 521e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE_FOR_FREE(ptr); 531e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_free(ptr, &stack); 541e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 551e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 561e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 571e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// TODO(glider): do we need both zones? 583f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryanystatic malloc_zone_t *system_malloc_zone = 0; 593f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryanystatic malloc_zone_t *system_purgeable_zone = 0; 601e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 611e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// We need to provide wrappers around all the libc functions. 621e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanynamespace { 631e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// TODO(glider): the mz_* functions should be united with the Linux wrappers, 641e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// as they are basically copied from there. 651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanysize_t mz_size(malloc_zone_t* zone, const void* ptr) { 661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // Fast path: check whether this pointer belongs to the original malloc zone. 671e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // We cannot just call malloc_zone_from_ptr(), because it in turn 681e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // calls our mz_size(). 691e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (system_malloc_zone) { 701e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if ((system_malloc_zone->size)(system_malloc_zone, ptr)) return 0; 711e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 724fd95f141f78906570c15a8a3b4cf0a7b50a201dAlexey Samsonov return asan_mz_size(ptr); 731e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 741e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 751e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid *mz_malloc(malloc_zone_t *zone, size_t size) { 761e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (!asan_inited) { 771e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany CHECK(system_malloc_zone); 781e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return malloc_zone_malloc(system_malloc_zone, size); 791e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 801e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE_FOR_MALLOC; 811e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return asan_malloc(size, &stack); 821e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 831e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 841e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid *cf_malloc(CFIndex size, CFOptionFlags hint, void *info) { 851e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (!asan_inited) { 861e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany CHECK(system_malloc_zone); 871e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return malloc_zone_malloc(system_malloc_zone, size); 881e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 891e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE_FOR_MALLOC; 901e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return asan_malloc(size, &stack); 911e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 921e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 931e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid *mz_calloc(malloc_zone_t *zone, size_t nmemb, size_t size) { 941e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (!asan_inited) { 9509672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym. 961e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany const size_t kCallocPoolSize = 1024; 973f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany static uptr calloc_memory_for_dlsym[kCallocPoolSize]; 981e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany static size_t allocated; 991e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany size_t size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize; 1001e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany void *mem = (void*)&calloc_memory_for_dlsym[allocated]; 1011e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany allocated += size_in_words; 1021e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany CHECK(allocated < kCallocPoolSize); 1031e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return mem; 1041e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 1051e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE_FOR_MALLOC; 1061e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return asan_calloc(nmemb, size, &stack); 1071e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 1081e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 1091e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid *mz_valloc(malloc_zone_t *zone, size_t size) { 1101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (!asan_inited) { 1111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany CHECK(system_malloc_zone); 1121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return malloc_zone_valloc(system_malloc_zone, size); 1131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 1141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE_FOR_MALLOC; 1151e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return asan_memalign(kPageSize, size, &stack); 1161e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 1171e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 1181e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid print_zone_for_ptr(void *ptr) { 1191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany malloc_zone_t *orig_zone = malloc_zone_from_ptr(ptr); 1201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (orig_zone) { 1211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (orig_zone->zone_name) { 1221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany Printf("malloc_zone_from_ptr(%p) = %p, which is %s\n", 1231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ptr, orig_zone, orig_zone->zone_name); 1241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } else { 1251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany Printf("malloc_zone_from_ptr(%p) = %p, which doesn't have a name\n", 1261e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ptr, orig_zone); 1271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 1281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } else { 1293f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany Printf("malloc_zone_from_ptr(%p) = 0\n", ptr); 1301e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 1311e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 1321e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 1331e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// TODO(glider): the allocation callbacks need to be refactored. 1341e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid mz_free(malloc_zone_t *zone, void *ptr) { 1351e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (!ptr) return; 1361e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany malloc_zone_t *orig_zone = malloc_zone_from_ptr(ptr); 1371e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // For some reason Chromium calls mz_free() for pointers that belong to 1381e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // DefaultPurgeableMallocZone instead of asan_zone. We might want to 1391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // fix this someday. 1401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (orig_zone == system_purgeable_zone) { 1411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany system_purgeable_zone->free(system_purgeable_zone, ptr); 1421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return; 1431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 1444fd95f141f78906570c15a8a3b4cf0a7b50a201dAlexey Samsonov if (asan_mz_size(ptr)) { 1451e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE_FOR_FREE(ptr); 1461e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_free(ptr, &stack); 1471e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } else { 1481e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // Let us just leak this memory for now. 1491e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany Printf("mz_free(%p) -- attempting to free unallocated memory.\n" 1501e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany "AddressSanitizer is ignoring this error on Mac OS now.\n", ptr); 1511e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany print_zone_for_ptr(ptr); 1521e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE_FOR_FREE(ptr); 1531e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany stack.PrintStack(); 1541e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return; 1551e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 1561e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 1571e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 1581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid cf_free(void *ptr, void *info) { 1591e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (!ptr) return; 1601e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany malloc_zone_t *orig_zone = malloc_zone_from_ptr(ptr); 1611e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // For some reason Chromium calls mz_free() for pointers that belong to 1621e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // DefaultPurgeableMallocZone instead of asan_zone. We might want to 1631e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // fix this someday. 1641e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (orig_zone == system_purgeable_zone) { 1651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany system_purgeable_zone->free(system_purgeable_zone, ptr); 1661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return; 1671e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 1684fd95f141f78906570c15a8a3b4cf0a7b50a201dAlexey Samsonov if (asan_mz_size(ptr)) { 1691e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE_FOR_FREE(ptr); 1701e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_free(ptr, &stack); 1711e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } else { 1721e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // Let us just leak this memory for now. 1731e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany Printf("cf_free(%p) -- attempting to free unallocated memory.\n" 1741e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany "AddressSanitizer is ignoring this error on Mac OS now.\n", ptr); 1751e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany print_zone_for_ptr(ptr); 1761e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE_FOR_FREE(ptr); 1771e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany stack.PrintStack(); 1781e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return; 1791e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 1801e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 1811e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 1821e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid *mz_realloc(malloc_zone_t *zone, void *ptr, size_t size) { 1831e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (!ptr) { 1841e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE_FOR_MALLOC; 1851e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return asan_malloc(size, &stack); 1861e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } else { 1874fd95f141f78906570c15a8a3b4cf0a7b50a201dAlexey Samsonov if (asan_mz_size(ptr)) { 1881e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE_FOR_MALLOC; 1891e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return asan_realloc(ptr, size, &stack); 1901e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } else { 1911e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // We can't recover from reallocating an unknown address, because 1921e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // this would require reading at most |size| bytes from 1931e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // potentially unaccessible memory. 1941e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany Printf("mz_realloc(%p) -- attempting to realloc unallocated memory.\n" 1951e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany "This is an unrecoverable problem, exiting now.\n", ptr); 1961e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany print_zone_for_ptr(ptr); 1971e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE_FOR_FREE(ptr); 1981e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany stack.PrintStack(); 1991e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ShowStatsAndAbort(); 2003f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany return 0; // unreachable 2011e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 2021e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 2031e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 2041e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 2051e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid *cf_realloc(void *ptr, CFIndex size, CFOptionFlags hint, void *info) { 2061e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (!ptr) { 2071e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE_FOR_MALLOC; 2081e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return asan_malloc(size, &stack); 2091e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } else { 2104fd95f141f78906570c15a8a3b4cf0a7b50a201dAlexey Samsonov if (asan_mz_size(ptr)) { 2111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE_FOR_MALLOC; 2121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return asan_realloc(ptr, size, &stack); 2131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } else { 2141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // We can't recover from reallocating an unknown address, because 2151e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // this would require reading at most |size| bytes from 2161e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // potentially unaccessible memory. 2171e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany Printf("cf_realloc(%p) -- attempting to realloc unallocated memory.\n" 2181e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany "This is an unrecoverable problem, exiting now.\n", ptr); 2191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany print_zone_for_ptr(ptr); 2201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE_FOR_FREE(ptr); 2211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany stack.PrintStack(); 2221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ShowStatsAndAbort(); 2233f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany return 0; // unreachable 2241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 2251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 2261e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 2271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 2281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid mz_destroy(malloc_zone_t* zone) { 2291e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // A no-op -- we will not be destroyed! 2301e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany Printf("mz_destroy() called -- ignoring\n"); 2311e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 2321e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // from AvailabilityMacros.h 2331e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#if defined(MAC_OS_X_VERSION_10_6) && \ 2341e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 2351e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid *mz_memalign(malloc_zone_t *zone, size_t align, size_t size) { 2361e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (!asan_inited) { 2371e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany CHECK(system_malloc_zone); 2381e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return malloc_zone_memalign(system_malloc_zone, align, size); 2391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 2401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany GET_STACK_TRACE_HERE_FOR_MALLOC; 2411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return asan_memalign(align, size, &stack); 2421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 2431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 244c1ef2a0b8022f200f8bbb36641df866c4369876dDaniel Dunbar// This function is currently unused, and we build with -Werror. 245c1ef2a0b8022f200f8bbb36641df866c4369876dDaniel Dunbar#if 0 2461e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid mz_free_definite_size(malloc_zone_t* zone, void *ptr, size_t size) { 2471e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // TODO(glider): check that |size| is valid. 2481e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany UNIMPLEMENTED(); 2491e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 2501e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#endif 251c1ef2a0b8022f200f8bbb36641df866c4369876dDaniel Dunbar#endif 2521e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 2531e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// malloc_introspection callbacks. I'm not clear on what all of these do. 2541e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanykern_return_t mi_enumerator(task_t task, void *, 2551e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany unsigned type_mask, vm_address_t zone_address, 2561e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany memory_reader_t reader, 2571e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany vm_range_recorder_t recorder) { 2581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // Should enumerate all the pointers we have. Seems like a lot of work. 2591e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return KERN_FAILURE; 2601e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 2611e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 2621e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanysize_t mi_good_size(malloc_zone_t *zone, size_t size) { 2631e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // I think it's always safe to return size, but we maybe could do better. 2641e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return size; 2651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 2661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 2671e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyboolean_t mi_check(malloc_zone_t *zone) { 2681e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany UNIMPLEMENTED(); 2691e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return true; 2701e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 2711e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 2721e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid mi_print(malloc_zone_t *zone, boolean_t verbose) { 2731e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany UNIMPLEMENTED(); 2741e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return; 2751e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 2761e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 2771e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid mi_log(malloc_zone_t *zone, void *address) { 2781e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // I don't think we support anything like this 2791e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 2801e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 2811e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid mi_force_lock(malloc_zone_t *zone) { 2824fd95f141f78906570c15a8a3b4cf0a7b50a201dAlexey Samsonov asan_mz_force_lock(); 2831e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 2841e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 2851e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid mi_force_unlock(malloc_zone_t *zone) { 2864fd95f141f78906570c15a8a3b4cf0a7b50a201dAlexey Samsonov asan_mz_force_unlock(); 2871e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 2881e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 289c1ef2a0b8022f200f8bbb36641df866c4369876dDaniel Dunbar// This function is currently unused, and we build with -Werror. 290c1ef2a0b8022f200f8bbb36641df866c4369876dDaniel Dunbar#if 0 2911e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid mi_statistics(malloc_zone_t *zone, malloc_statistics_t *stats) { 2921e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // TODO(csilvers): figure out how to fill these out 2931e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // TODO(glider): port this from tcmalloc when ready. 2941e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany stats->blocks_in_use = 0; 2951e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany stats->size_in_use = 0; 2961e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany stats->max_size_in_use = 0; 2971e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany stats->size_allocated = 0; 2981e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 299c1ef2a0b8022f200f8bbb36641df866c4369876dDaniel Dunbar#endif 3001e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 301eeb719154538f38ffd54d8d3bfd8e113b97fe6a1Eli Friedman#if defined(MAC_OS_X_VERSION_10_6) && \ 302eeb719154538f38ffd54d8d3bfd8e113b97fe6a1Eli Friedman MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 3031e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyboolean_t mi_zone_locked(malloc_zone_t *zone) { 3041e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // UNIMPLEMENTED(); 3051e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return false; 3061e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 307eeb719154538f38ffd54d8d3bfd8e113b97fe6a1Eli Friedman#endif 3081e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3091e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} // unnamed namespace 3101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyextern bool kCFUseCollectableAllocator; // is GC on? 3121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanynamespace __asan { 3141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid ReplaceSystemMalloc() { 3151e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany static malloc_introspection_t asan_introspection; 316ebb9702cff96192c6a6ea963037929ca7ed60eaeAlexander Potapenko // Ok to use internal_memset, these places are not performance-critical. 317ebb9702cff96192c6a6ea963037929ca7ed60eaeAlexander Potapenko internal_memset(&asan_introspection, 0, sizeof(asan_introspection)); 3181e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_introspection.enumerator = &mi_enumerator; 3201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_introspection.good_size = &mi_good_size; 3211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_introspection.check = &mi_check; 3221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_introspection.print = &mi_print; 3231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_introspection.log = &mi_log; 3241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_introspection.force_lock = &mi_force_lock; 3251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_introspection.force_unlock = &mi_force_unlock; 3261e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany static malloc_zone_t asan_zone; 328ebb9702cff96192c6a6ea963037929ca7ed60eaeAlexander Potapenko internal_memset(&asan_zone, 0, sizeof(malloc_zone_t)); 3291e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3301e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // Start with a version 4 zone which is used for OS X 10.4 and 10.5. 3311e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_zone.version = 4; 3321e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_zone.zone_name = "asan"; 3331e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_zone.size = &mz_size; 3341e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_zone.malloc = &mz_malloc; 3351e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_zone.calloc = &mz_calloc; 3361e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_zone.valloc = &mz_valloc; 3371e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_zone.free = &mz_free; 3381e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_zone.realloc = &mz_realloc; 3391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_zone.destroy = &mz_destroy; 3403f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany asan_zone.batch_malloc = 0; 3413f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany asan_zone.batch_free = 0; 3421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_zone.introspect = &asan_introspection; 3431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3441e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // from AvailabilityMacros.h 3451e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#if defined(MAC_OS_X_VERSION_10_6) && \ 3461e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 3471e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // Switch to version 6 on OSX 10.6 to support memalign. 3481e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_zone.version = 6; 3491e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_zone.free_definite_size = 0; 3501e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_zone.memalign = &mz_memalign; 3511e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asan_introspection.zone_locked = &mi_zone_locked; 3521e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3531e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // Request the default purgable zone to force its creation. The 3541e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // current default zone is registered with the purgable zone for 3551e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // doing tiny and small allocs. Sadly, it assumes that the default 3561e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // zone is the szone implementation from OS X and will crash if it 3571e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // isn't. By creating the zone now, this will be true and changing 3581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // the default zone won't cause a problem. (OS X 10.6 and higher.) 3591e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany system_purgeable_zone = malloc_default_purgeable_zone(); 3601e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#endif 3611e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3621e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // Register the ASan zone. At this point, it will not be the 3631e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // default zone. 3641e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany malloc_zone_register(&asan_zone); 3651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // Unregister and reregister the default zone. Unregistering swaps 3671e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // the specified zone with the last one registered which for the 3681e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // default zone makes the more recently registered zone the default 3691e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // zone. The default zone is then re-registered to ensure that 3701e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // allocations made from it earlier will be handled correctly. 3711e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // Things are not guaranteed to work that way, but it's how they work now. 3721e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany system_malloc_zone = malloc_default_zone(); 3731e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany malloc_zone_unregister(system_malloc_zone); 3741e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany malloc_zone_register(system_malloc_zone); 3751e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // Make sure the default allocator was replaced. 3761e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany CHECK(malloc_default_zone() == &asan_zone); 3771e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3781e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (FLAG_replace_cfallocator) { 3791e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany static CFAllocatorContext asan_context = 3801e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany { /*version*/ 0, /*info*/ &asan_zone, 3813f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany /*retain*/ 0, /*release*/ 0, 3823f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany /*copyDescription*/0, 3831e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany /*allocate*/ &cf_malloc, 3841e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany /*reallocate*/ &cf_realloc, 3851e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany /*deallocate*/ &cf_free, 3863f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany /*preferredSize*/ 0 }; 3871e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany CFAllocatorRef cf_asan = 3881e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany CFAllocatorCreate(kCFAllocatorUseContext, &asan_context); 3891e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany CFAllocatorSetDefault(cf_asan); 3901e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 3911e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 3921e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} // namespace __asan 393d6567c5166412f6acdde851e767c26f332d51d3dKostya Serebryany 394d6567c5166412f6acdde851e767c26f332d51d3dKostya Serebryany#endif // __APPLE__ 395