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