| OLD | NEW |
| 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 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 52 printf(args); \ | 52 printf(args); \ |
| 53 } while (false); | 53 } while (false); |
| 54 #else // !DEBUG | 54 #else // !DEBUG |
| 55 #define DUMP(args...) | 55 #define DUMP(args...) |
| 56 #endif // DEBUG | 56 #endif // DEBUG |
| 57 | 57 |
| 58 static char *shadow_offset = NULL; | 58 static char *shadow_offset = NULL; |
| 59 | 59 |
| 60 static void __asan_error(char *, int); | 60 static void __asan_error(char *, int); |
| 61 static void __asan_check(char *, int, bool); | 61 static void __asan_check(char *, int, bool); |
| 62 static void __asan_get_redzones(char *, char **, char **); |
| 62 | 63 |
| 63 void __asan_init(int, void **, int *); | 64 void __asan_init(int, void **, int *); |
| 64 void __asan_check_load(char *, int); | 65 void __asan_check_load(char *, int); |
| 65 void __asan_check_store(char *, int); | 66 void __asan_check_store(char *, int); |
| 66 void *__asan_malloc(size_t); | 67 void *__asan_malloc(size_t); |
| 68 void *__asan_calloc(size_t, size_t); |
| 69 void *__asan_realloc(char *, size_t); |
| 67 void __asan_free(char *); | 70 void __asan_free(char *); |
| 68 void __asan_poison(char *, int); | 71 void __asan_poison(char *, int); |
| 69 void __asan_unpoison(char *, int); | 72 void __asan_unpoison(char *, int); |
| 70 | 73 |
| 71 static void __asan_error(char *ptr, int size) { | 74 static void __asan_error(char *ptr, int size) { |
| 72 fprintf(stderr, "Illegal access of %d bytes at %p\n", size, ptr); | 75 fprintf(stderr, "Illegal access of %d bytes at %p\n", size, ptr); |
| 73 abort(); | 76 abort(); |
| 74 } | 77 } |
| 75 | 78 |
| 76 // check only the first byte of each word unless strict | 79 // check only the first byte of each word unless strict |
| 77 static void __asan_check(char *ptr, int size, bool strict) { | 80 static void __asan_check(char *ptr, int size, bool strict) { |
| 78 assert(strict || (uintptr_t)ptr % WORD_SIZE == 0); | 81 assert(strict || (uintptr_t)ptr % WORD_SIZE == 0); |
| 79 DUMP("%s check %d bytes at %p\n", (strict) ? "strict" : "loose", size, ptr); | 82 DUMP("%s check %d bytes at %p\n", (strict) ? "strict" : "loose", size, ptr); |
| 80 char *end = ptr + size; | 83 char *end = ptr + size; |
| 81 int step = (strict) ? 1 : WORD_SIZE; | 84 int step = (strict) ? 1 : WORD_SIZE; |
| 82 for (char *cur = ptr; cur < end; cur += step) { | 85 for (char *cur = ptr; cur < end; cur += step) { |
| 83 char shadow = *(char *)MEM2SHADOW(cur); | 86 char shadow = *(char *)MEM2SHADOW(cur); |
| 84 DUMP("checking %p against %p with shadow %d\n", cur, MEM2SHADOW(cur), | 87 DUMP("checking %p against %p with shadow %d\n", cur, MEM2SHADOW(cur), |
| 85 shadow); | 88 shadow); |
| 86 if (shadow != 0 && (shadow < 0 || SHADOW_OFFSET(cur) >= shadow)) { | 89 if (shadow != 0 && (shadow < 0 || SHADOW_OFFSET(cur) >= shadow)) { |
| 87 __asan_error(ptr, size); | 90 __asan_error(ptr, size); |
| 88 } | 91 } |
| 89 } | 92 } |
| 90 } | 93 } |
| 91 | 94 |
| 95 static void __asan_get_redzones(char *ptr, char **left, char **right) { |
| 96 char *rz_left = ptr - RZ_SIZE; |
| 97 char *rz_right = *(char **)rz_left; |
| 98 if (left != NULL) |
| 99 *left = rz_left; |
| 100 if (right != NULL) |
| 101 *right = rz_right; |
| 102 } |
| 103 |
| 92 void __asan_check_load(char *ptr, int size) { | 104 void __asan_check_load(char *ptr, int size) { |
| 93 // aligned single word accesses may be widened single byte accesses, but for | 105 // aligned single word accesses may be widened single byte accesses, but for |
| 94 // all else use strict check | 106 // all else use strict check |
| 95 bool strict = !((uintptr_t)ptr % WORD_SIZE == 0 && size == WORD_SIZE); | 107 bool strict = !((uintptr_t)ptr % WORD_SIZE == 0 && size == WORD_SIZE); |
| 96 __asan_check(ptr, size, strict); | 108 __asan_check(ptr, size, strict); |
| 97 } | 109 } |
| 98 | 110 |
| 99 void __asan_check_store(char *ptr, int size) { | 111 void __asan_check_store(char *ptr, int size) { |
| 100 // stores may never be partially out of bounds so use strict check | 112 // stores may never be partially out of bounds so use strict check |
| 101 bool strict = true; | 113 bool strict = true; |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 154 return ret; | 166 return ret; |
| 155 } | 167 } |
| 156 | 168 |
| 157 void *__asan_calloc(size_t nmemb, size_t size) { | 169 void *__asan_calloc(size_t nmemb, size_t size) { |
| 158 size_t alloc_size = nmemb * size; | 170 size_t alloc_size = nmemb * size; |
| 159 void *ret = __asan_malloc(alloc_size); | 171 void *ret = __asan_malloc(alloc_size); |
| 160 memset(ret, 0, alloc_size); | 172 memset(ret, 0, alloc_size); |
| 161 return ret; | 173 return ret; |
| 162 } | 174 } |
| 163 | 175 |
| 176 void *__asan_realloc(char *ptr, size_t size) { |
| 177 if (ptr == NULL) |
| 178 return __asan_malloc(size); |
| 179 if (size == 0) { |
| 180 __asan_free(ptr); |
| 181 return NULL; |
| 182 } |
| 183 char *rz_right; |
| 184 __asan_get_redzones(ptr, NULL, &rz_right); |
| 185 size_t old_size = rz_right - ptr; |
| 186 if (size == old_size) |
| 187 return ptr; |
| 188 char *new_alloc = __asan_malloc(size); |
| 189 if (new_alloc == NULL) |
| 190 return NULL; |
| 191 size_t copyable = (size < old_size) ? size : old_size; |
| 192 memcpy(new_alloc, ptr, copyable); |
| 193 __asan_free(ptr); |
| 194 return new_alloc; |
| 195 } |
| 196 |
| 164 void __asan_free(char *ptr) { | 197 void __asan_free(char *ptr) { |
| 165 DUMP("free() called on %p\n", ptr); | 198 DUMP("free() called on %p\n", ptr); |
| 166 void *rz_left = ptr - RZ_SIZE; | 199 void *rz_left, *rz_right; |
| 167 void *rz_right = *(void **)rz_left; | 200 __asan_get_redzones(ptr, &rz_left, &rz_right); |
| 168 size_t rz_right_size = *(size_t *)rz_right; | 201 size_t rz_right_size = *(size_t *)rz_right; |
| 169 __asan_unpoison(rz_left, RZ_SIZE); | 202 __asan_unpoison(rz_left, RZ_SIZE); |
| 170 __asan_unpoison(rz_right, rz_right_size); | 203 __asan_unpoison(rz_right, rz_right_size); |
| 171 free(rz_left); | 204 free(rz_left); |
| 172 } | 205 } |
| 173 | 206 |
| 174 void __asan_poison(char *ptr, int size) { | 207 void __asan_poison(char *ptr, int size) { |
| 175 char *end = ptr + size; | 208 char *end = ptr + size; |
| 176 assert(IS_SHADOW_ALIGNED(end)); | 209 assert(IS_SHADOW_ALIGNED(end)); |
| 177 // redzones should be no greater than RZ_SIZE + RZ_SIZE-1 for alignment | 210 // redzones should be no greater than RZ_SIZE + RZ_SIZE-1 for alignment |
| (...skipping 15 matching lines...) Expand all Loading... |
| 193 assert(size < 2 * RZ_SIZE); | 226 assert(size < 2 * RZ_SIZE); |
| 194 DUMP("unpoison %d bytes at %p: %p - %p\n", size, ptr, MEM2SHADOW(ptr), | 227 DUMP("unpoison %d bytes at %p: %p - %p\n", size, ptr, MEM2SHADOW(ptr), |
| 195 MEM2SHADOW(end)); | 228 MEM2SHADOW(end)); |
| 196 *(char *)MEM2SHADOW(ptr) = 0; | 229 *(char *)MEM2SHADOW(ptr) = 0; |
| 197 ptr += SHADOW_OFFSET(size); | 230 ptr += SHADOW_OFFSET(size); |
| 198 assert(IS_SHADOW_ALIGNED(ptr)); | 231 assert(IS_SHADOW_ALIGNED(ptr)); |
| 199 for (; ptr != end; ptr += SHADOW_SCALE) { | 232 for (; ptr != end; ptr += SHADOW_SCALE) { |
| 200 *(char *)MEM2SHADOW(ptr) = 0; | 233 *(char *)MEM2SHADOW(ptr) = 0; |
| 201 } | 234 } |
| 202 } | 235 } |
| OLD | NEW |