-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathasan.c
106 lines (87 loc) · 2.89 KB
/
asan.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#include <darwintest.h>
#include <dlfcn.h>
#include <malloc/malloc.h>
#include <setjmp.h>
#include <stdlib.h>
#include "sanitizer/asan_interface.h"
T_GLOBAL_META(T_META_RUN_CONCURRENTLY(true));
T_DECL(asan_sanity, "ASan Sanity Check", T_META_CHECK_LEAKS(NO))
{
const char *dylib_path =
TARGET_OS_OSX ? "@rpath/libclang_rt.asan_osx_dynamic.dylib" :
TARGET_OS_IOS ? "@rpath/libclang_rt.asan_ios_dynamic.dylib" :
TARGET_OS_TV ? "@rpath/libclang_rt.asan_tvos_dynamic.dylib" :
TARGET_OS_WATCH ? "@rpath/libclang_rt.asan_watchos_dynamic.dylib" :
TARGET_OS_BRIDGE ? "@rpath/libclang_rt.asan_bridgeos_dynamic.dylib" :
NULL;
void *asan_dylib = dlopen(dylib_path, RTLD_NOLOAD);
T_ASSERT_NOTNULL(asan_dylib, "ASan dylib loaded");
void *ptr = malloc(16);
free(ptr);
T_PASS("I didn't crash!");
}
jmp_buf longjmp_env = {0};
bool asan_report_hit = false;
char *asan_report = NULL;
void asan_report_handler(const char *report) {
asan_report_hit = true;
asan_report = strdup(report);
longjmp(longjmp_env, 1);
}
__attribute__((optnone, noinline))
void write_byte(void *ptr, size_t offset) {
((char *)ptr)[offset] = 'x';
}
T_DECL(asan_use_after_free, "ASan Detects use-after-free", T_META_CHECK_LEAKS(NO))
{
asan_report = NULL;
asan_report_hit = false;
__asan_set_error_report_callback(asan_report_handler);
if (setjmp(longjmp_env) == 0) {
char *ptr = malloc(16);
free(ptr);
write_byte(ptr, 10);
T_FAIL("use-after-free not detected");
}
T_EXPECT_EQ(asan_report_hit, true, "asan finds use-after-free");
T_EXPECT_NOTNULL(strstr(asan_report, "AddressSanitizer: heap-use-after-free"), "asan header");
}
T_DECL(asan_heap_buffer_overflow, "ASan Detects heap-buffer-overflow", T_META_CHECK_LEAKS(NO))
{
asan_report = NULL;
asan_report_hit = false;
__asan_set_error_report_callback(asan_report_handler);
if (setjmp(longjmp_env) == 0) {
char *ptr = malloc(16);
write_byte(ptr, 17);
free(ptr);
T_FAIL("heap-buffer-overflow not detected");
}
T_EXPECT_EQ(asan_report_hit, true, "asan finds heap-buffer-overflow");
T_EXPECT_NOTNULL(strstr(asan_report, "AddressSanitizer: heap-buffer-overflow"), "asan header");
}
static malloc_zone_t *
call_malloc_zone_from_ptr(void)
{
void *ptr = malloc(5);
malloc_zone_t *zone = malloc_zone_from_ptr(ptr);
free(ptr);
return zone;
}
extern int32_t malloc_num_zones;
extern malloc_zone_t **malloc_zones;
T_DECL(asan_zone0, "Ensure we return the real zone 0 (not the virtual zone)")
{
malloc_zone_t *zone0 = malloc_zones[0];
T_EXPECT_EQ(malloc_default_zone(), zone0, NULL);
T_EXPECT_EQ(call_malloc_zone_from_ptr(), zone0, NULL);
}
T_DECL(pgm_interaction, "Ensure we never enable PGM together with ASan",
T_META_ENVVAR("MallocProbGuard=1"))
{
for (uint32_t i = 0; i < malloc_num_zones; i++) {
const char *zone_name = malloc_get_zone_name(malloc_zones[i]);
T_QUIET; T_EXPECT_NE_STR(zone_name, "ProbGuardMallocZone", NULL);
}
T_PASS("No PGM zone installed");
}