summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/sanitizer_common/sanitizer_malloc_mac.inc11
-rw-r--r--test/sanitizer_common/TestCases/Darwin/malloc_zone.cpp45
2 files changed, 55 insertions, 1 deletions
diff --git a/lib/sanitizer_common/sanitizer_malloc_mac.inc b/lib/sanitizer_common/sanitizer_malloc_mac.inc
index 3f3581eeb..11adbe5c2 100644
--- a/lib/sanitizer_common/sanitizer_malloc_mac.inc
+++ b/lib/sanitizer_common/sanitizer_malloc_mac.inc
@@ -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"
diff --git a/test/sanitizer_common/TestCases/Darwin/malloc_zone.cpp b/test/sanitizer_common/TestCases/Darwin/malloc_zone.cpp
new file mode 100644
index 000000000..fd6ef0362
--- /dev/null
+++ b/test/sanitizer_common/TestCases/Darwin/malloc_zone.cpp
@@ -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;
+}