[Sanitizer][Darwin] Add interceptor for malloc_zone_from_ptr

Ensure that malloc_default_zone and malloc_zone_from_ptr return the
sanitizer-installed malloc zone even when MallocStackLogging (MSL) is
requested. This prevents crashes in certain situations. Note that the
sanitizers and MSL cannot be used together. If both are enabled, MSL
functionality is essentially deactivated since it only hooks the default
allocator which is replaced by a custom sanitizer allocator.

rdar://53686175

Reviewed By: kubamracek

Differential Revision: https://reviews.llvm.org/D65990

llvm-svn: 368492
This commit is contained in:
Julian Lettner 2019-08-09 21:46:32 +00:00
parent 0fd073b1bf
commit 5ef4b190d9
2 changed files with 55 additions and 1 deletions

View File

@ -91,6 +91,15 @@ INTERCEPTOR(malloc_zone_t *, malloc_default_zone, void) {
return &sanitizer_zone;
}
INTERCEPTOR(malloc_zone_t *, malloc_zone_from_ptr, const void *ptr) {
COMMON_MALLOC_ENTER();
size_t size = sanitizer_zone.size(&sanitizer_zone, ptr);
if (size) { // Claimed by sanitizer zone?
return &sanitizer_zone;
}
return REAL(malloc_zone_from_ptr)(ptr);
}
INTERCEPTOR(malloc_zone_t *, malloc_default_purgeable_zone, void) {
// FIXME: ASan should support purgeable allocations.
// https://github.com/google/sanitizers/issues/139
@ -226,7 +235,7 @@ void __sanitizer_mz_free(malloc_zone_t *zone, void *ptr) {
}
#define GET_ZONE_FOR_PTR(ptr) \
malloc_zone_t *zone_ptr = malloc_zone_from_ptr(ptr); \
malloc_zone_t *zone_ptr = WRAP(malloc_zone_from_ptr)(ptr); \
const char *zone_name = (zone_ptr == 0) ? 0 : zone_ptr->zone_name
extern "C"

View File

@ -0,0 +1,45 @@
// Check that malloc_default_zone and malloc_zone_from_ptr return the
// sanitizer-installed malloc zone even when MallocStackLogging (MSL) is
// requested. This prevents crashes in certain situations. Note that the
// sanitizers and MSL cannot be used together. If both are enabled, MSL
// functionality is essentially deactivated since it only hooks the default
// allocator which is replaced by a custom sanitizer allocator.
//
// MSL=lite creates its own special malloc zone, copies the passed zone name,
// and leaks it.
// RUN: echo "leak:create_and_insert_msl_lite_zone" >> lsan.supp
//
// RUN: %clangxx -g %s -o %t
// RUN: %run %t | FileCheck %s
// RUN: %env MallocStackLogging=lite LSAN_OPTIONS=suppressions=lsan.supp %run %t | FileCheck %s
// RUN: %env MallocStackLogging=full %run %t | FileCheck %s
//
// UBSan does not install a malloc zone.
// XFAIL: ubsan
//
#include <malloc/malloc.h>
#include <stdlib.h>
#include <stdio.h>
int main(void) {
malloc_zone_t *default_zone = malloc_default_zone();
printf("default zone name: %s\n", malloc_get_zone_name(default_zone));
// CHECK: default zone name: {{a|l|t}}san
void *ptr1 = malloc(10);
void *ptr2 = malloc_zone_malloc(default_zone, 10);
malloc_zone_t* zone1 = malloc_zone_from_ptr(ptr1);
malloc_zone_t* zone2 = malloc_zone_from_ptr(ptr2);
printf("zone1: %d\n", zone1 == default_zone);
printf("zone2: %d\n", zone2 == default_zone);
// CHECK: zone1: 1
// CHECK: zone2: 1
free(ptr1);
malloc_zone_free(zone2, ptr2);
return 0;
}