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