Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(203)

Side by Side Diff: runtime/szrt_asan.c

Issue 2256673004: Subzero: Added address of bad instruction to error output (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Clarified error message Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | tests_lit/asan_tests/doublefree.ll » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 //===- subzero/runtime/szrt_asan.c - AddressSanitizer Runtime -----*- C -*-===// 1 //===- subzero/runtime/szrt_asan.c - AddressSanitizer Runtime -----*- C -*-===//
2 // 2 //
3 // The Subzero Code Generator 3 // The Subzero Code Generator
4 // 4 //
5 // This file is distributed under the University of Illinois Open Source 5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details. 6 // License. See LICENSE.TXT for details.
7 // 7 //
8 //===----------------------------------------------------------------------===// 8 //===----------------------------------------------------------------------===//
9 /// 9 ///
10 /// \file 10 /// \file
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
83 do { \ 83 do { \
84 printf(args); \ 84 printf(args); \
85 } while (false); 85 } while (false);
86 #else // !DEBUG 86 #else // !DEBUG
87 #define DUMP(args...) 87 #define DUMP(args...)
88 #endif // DEBUG 88 #endif // DEBUG
89 89
90 static char *shadow_offset = NULL; 90 static char *shadow_offset = NULL;
91 91
92 static bool __asan_check(char *, int); 92 static bool __asan_check(char *, int);
93 static void __asan_error(char *, int, int); 93 static void __asan_error(char *, int, int, void *);
94 static void __asan_get_redzones(char *, char **, char **); 94 static void __asan_get_redzones(char *, char **, char **);
95 95
96 void __asan_init(int, void **, int *); 96 void __asan_init(int, void **, int *);
97 void __asan_check_load(char *, int); 97 void __asan_check_load(char *, int);
98 void __asan_check_store(char *, int); 98 void __asan_check_store(char *, int);
99 void *__asan_malloc(size_t); 99 void *__asan_malloc(size_t);
100 void *__asan_calloc(size_t, size_t); 100 void *__asan_calloc(size_t, size_t);
101 void *__asan_realloc(char *, size_t); 101 void *__asan_realloc(char *, size_t);
102 void __asan_free(char *); 102 void __asan_free(char *);
103 void __asan_poison(char *, int, char); 103 void __asan_poison(char *, int, char);
104 void __asan_unpoison(char *, int); 104 void __asan_unpoison(char *, int);
105 105
106 struct quarantine_entry { 106 struct quarantine_entry {
107 struct quarantine_entry *next; 107 struct quarantine_entry *next;
108 size_t size; 108 size_t size;
109 }; 109 };
110 110
111 mutex_t quarantine_lock = MUTEX_INITIALIZER; 111 mutex_t quarantine_lock = MUTEX_INITIALIZER;
112 uint64_t quarantine_size = 0; 112 uint64_t quarantine_size = 0;
113 struct quarantine_entry *quarantine_head = NULL; 113 struct quarantine_entry *quarantine_head = NULL;
114 struct quarantine_entry *quarantine_tail = NULL; 114 struct quarantine_entry *quarantine_tail = NULL;
115 115
116 static void __asan_error(char *ptr, int size, int access) { 116 static void __asan_error(char *ptr, int size, int access, void *ret_addr) {
117 char *shadow_addr = MEM2SHADOW(ptr); 117 char *shadow_addr = MEM2SHADOW(ptr);
118 char shadow_val = *shadow_addr; 118 char shadow_val = *shadow_addr;
119 if (shadow_val > 0) 119 if (shadow_val > 0)
120 shadow_val = *(shadow_addr + 1); 120 shadow_val = *(shadow_addr + 1);
121 assert(access == ACCESS_LOAD || access == ACCESS_STORE); 121 assert(access == ACCESS_LOAD || access == ACCESS_STORE);
122 const char *access_name = access_names[access]; 122 const char *access_name = access_names[access];
123 assert(shadow_val == STACK_POISON_VAL || shadow_val == HEAP_POISON_VAL || 123 assert(shadow_val == STACK_POISON_VAL || shadow_val == HEAP_POISON_VAL ||
124 shadow_val == GLOBAL_POISON_VAL || shadow_val == FREED_POISON_VAL); 124 shadow_val == GLOBAL_POISON_VAL || shadow_val == FREED_POISON_VAL);
125 const char *memtype = memtype_names[MEMTYPE_INDEX(shadow_val)]; 125 const char *memtype = memtype_names[MEMTYPE_INDEX(shadow_val)];
126 fprintf(stderr, "Illegal %d byte %s %s object at %p\n", size, access_name, 126 fprintf(stderr, "%p: Illegal %d byte %s %s object at %p\n", ret_addr, size,
127 memtype, ptr); 127 access_name, memtype, ptr);
128 fprintf(stderr, "(address of __asan_error symbol is %p)\n", __asan_error);
128 abort(); 129 abort();
129 } 130 }
130 131
131 // check only the first byte of each word unless strict 132 // check only the first byte of each word unless strict
132 static bool __asan_check(char *ptr, int size) { 133 static bool __asan_check(char *ptr, int size) {
133 assert(size == 1 || size == 2 || size == 4 || size == 8); 134 assert(size == 1 || size == 2 || size == 4 || size == 8);
134 char *shadow_addr = (char *)MEM2SHADOW(ptr); 135 char *shadow_addr = (char *)MEM2SHADOW(ptr);
135 char shadow_val = *shadow_addr; 136 char shadow_val = *shadow_addr;
136 DUMP("check %d bytes at %p: %p + %d (%d)\n", size, ptr, shadow_addr, 137 DUMP("check %d bytes at %p: %p + %d (%d)\n", size, ptr, shadow_addr,
137 (uintptr_t)ptr % SHADOW_SCALE, shadow_val); 138 (uintptr_t)ptr % SHADOW_SCALE, shadow_val);
(...skipping 11 matching lines...) Expand all
149 if (right != NULL) 150 if (right != NULL)
150 *right = rz_right; 151 *right = rz_right;
151 } 152 }
152 153
153 void __asan_check_load(char *ptr, int size) { 154 void __asan_check_load(char *ptr, int size) {
154 // aligned single word accesses may be widened single byte accesses, but for 155 // aligned single word accesses may be widened single byte accesses, but for
155 // all else use strict check 156 // all else use strict check
156 int check_size = 157 int check_size =
157 (size == WORD_SIZE && (uintptr_t)ptr % WORD_SIZE == 0) ? 1 : size; 158 (size == WORD_SIZE && (uintptr_t)ptr % WORD_SIZE == 0) ? 1 : size;
158 if (!__asan_check(ptr, check_size)) 159 if (!__asan_check(ptr, check_size))
159 __asan_error(ptr, size, ACCESS_LOAD); 160 __asan_error(ptr, size, ACCESS_LOAD, __builtin_return_address(0));
160 } 161 }
161 162
162 void __asan_check_store(char *ptr, int size) { 163 void __asan_check_store(char *ptr, int size) {
163 // stores may never be partially out of bounds so use strict check 164 // stores may never be partially out of bounds so use strict check
164 if (!__asan_check(ptr, size)) 165 if (!__asan_check(ptr, size))
165 __asan_error(ptr, size, ACCESS_STORE); 166 __asan_error(ptr, size, ACCESS_STORE, __builtin_return_address(0));
166 } 167 }
167 168
168 void __asan_init(int n_rzs, void **rzs, int *rz_sizes) { 169 void __asan_init(int n_rzs, void **rzs, int *rz_sizes) {
169 // ensure the redzones are large enough to hold metadata 170 // ensure the redzones are large enough to hold metadata
170 assert(RZ_SIZE >= sizeof(void *) && RZ_SIZE >= sizeof(size_t)); 171 assert(RZ_SIZE >= sizeof(void *) && RZ_SIZE >= sizeof(size_t));
171 assert(shadow_offset == NULL); 172 assert(shadow_offset == NULL);
172 size_t length = (IS_32_BIT) ? SHADOW_LENGTH_32 : SHADOW_LENGTH_64; 173 size_t length = (IS_32_BIT) ? SHADOW_LENGTH_32 : SHADOW_LENGTH_64;
173 int prot = PROT_READ | PROT_WRITE; 174 int prot = PROT_READ | PROT_WRITE;
174 int flags = MAP_PRIVATE | MAP_ANONYMOUS; 175 int flags = MAP_PRIVATE | MAP_ANONYMOUS;
175 int fd = -1; 176 int fd = -1;
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
243 memcpy(new_alloc, ptr, copyable); 244 memcpy(new_alloc, ptr, copyable);
244 __asan_free(ptr); 245 __asan_free(ptr);
245 return new_alloc; 246 return new_alloc;
246 } 247 }
247 248
248 void __asan_free(char *ptr) { 249 void __asan_free(char *ptr) {
249 DUMP("free() called on %p\n", ptr); 250 DUMP("free() called on %p\n", ptr);
250 if (ptr == NULL) 251 if (ptr == NULL)
251 return; 252 return;
252 if (*(char *)MEM2SHADOW(ptr) == FREED_POISON_VAL) { 253 if (*(char *)MEM2SHADOW(ptr) == FREED_POISON_VAL) {
253 fprintf(stderr, "Double free of object at %p\n", ptr); 254 fprintf(stderr, "%p: Double free of object at %p\n",
255 __builtin_return_address(0), ptr);
256 fprintf(stderr, "(address of __asan_error symbol is %p)\n", __asan_error);
254 abort(); 257 abort();
255 } 258 }
256 char *rz_left, *rz_right; 259 char *rz_left, *rz_right;
257 __asan_get_redzones(ptr, &rz_left, &rz_right); 260 __asan_get_redzones(ptr, &rz_left, &rz_right);
258 size_t rz_right_size = *(size_t *)rz_right; 261 size_t rz_right_size = *(size_t *)rz_right;
259 size_t total_size = rz_right_size + (rz_right - rz_left); 262 size_t total_size = rz_right_size + (rz_right - rz_left);
260 __asan_poison(rz_left, total_size, FREED_POISON_VAL); 263 __asan_poison(rz_left, total_size, FREED_POISON_VAL);
261 264
262 // place allocation in quarantine 265 // place allocation in quarantine
263 struct quarantine_entry *entry = (struct quarantine_entry *)rz_left; 266 struct quarantine_entry *entry = (struct quarantine_entry *)rz_left;
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
305 void __asan_unpoison(char *ptr, int size) { 308 void __asan_unpoison(char *ptr, int size) {
306 char *end = ptr + size; 309 char *end = ptr + size;
307 assert(IS_SHADOW_ALIGNED(end)); 310 assert(IS_SHADOW_ALIGNED(end));
308 DUMP("unpoison %d bytes at %p: %p - %p\n", size, ptr, MEM2SHADOW(ptr), 311 DUMP("unpoison %d bytes at %p: %p - %p\n", size, ptr, MEM2SHADOW(ptr),
309 MEM2SHADOW(end)); 312 MEM2SHADOW(end));
310 *(char *)MEM2SHADOW(ptr) = 0; 313 *(char *)MEM2SHADOW(ptr) = 0;
311 ptr += SHADOW_OFFSET(size); 314 ptr += SHADOW_OFFSET(size);
312 assert(IS_SHADOW_ALIGNED(ptr)); 315 assert(IS_SHADOW_ALIGNED(ptr));
313 memset(MEM2SHADOW(ptr), 0, (end - ptr) >> SHADOW_SCALE_LOG2); 316 memset(MEM2SHADOW(ptr), 0, (end - ptr) >> SHADOW_SCALE_LOG2);
314 } 317 }
OLDNEW
« no previous file with comments | « no previous file | tests_lit/asan_tests/doublefree.ll » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698