Index: runtime/szrt_asan.c |
diff --git a/runtime/szrt_asan.c b/runtime/szrt_asan.c |
index 797f1b99b2a7a03c01085770c6b3b466ad50f9e7..a406b9323a9f0395e3d9ef0df4b51563d1aa8c28 100644 |
--- a/runtime/szrt_asan.c |
+++ b/runtime/szrt_asan.c |
@@ -32,7 +32,8 @@ |
// Assuming 48 bit address space on 64 bit systems |
#define SHADOW_LENGTH_64 (1u << (48 - SHADOW_SCALE_LOG2)) |
#define SHADOW_LENGTH_32 (1u << (32 - SHADOW_SCALE_LOG2)) |
-#define IS_32_BIT (sizeof(void *) == 4) |
+#define WORD_SIZE (sizeof(uint32_t)) |
+#define IS_32_BIT (sizeof(void *) == WORD_SIZE) |
#define SHADOW_OFFSET(p) ((uintptr_t)(p) % SHADOW_SCALE) |
#define IS_SHADOW_ALIGNED(p) (SHADOW_OFFSET(p) == 0) |
@@ -45,13 +46,51 @@ |
static char *shadow_offset = NULL; |
+static void __asan_error(char *, int); |
+static void __asan_check(char *, int, bool); |
+ |
void __asan_init(int, void **, int *); |
-void __asan_check(char *, int); |
+void __asan_check_load(char *, int); |
+void __asan_check_store(char *, int); |
void *__asan_malloc(size_t); |
void __asan_free(char *); |
void __asan_poison(char *, int); |
void __asan_unpoison(char *, int); |
+static void __asan_error(char *ptr, int size) { |
+ fprintf(stderr, "Illegal access of %d bytes at %p\n", size, ptr); |
+ abort(); |
+} |
+ |
+// check only the first byte of each word unless strict |
+static void __asan_check(char *ptr, int size, bool strict) { |
+ assert(strict || (uintptr_t)ptr % WORD_SIZE == 0); |
+ printf("%s check %d bytes at %p\n", (strict) ? "strict" : "loose", size, ptr); |
+ char *end = ptr + size; |
+ int step = (strict) ? 1 : WORD_SIZE; |
+ for (char *cur = ptr; cur < end; cur += step) { |
+ char shadow = *(char *)MEM2SHADOW(cur); |
+ printf("checking %p against %p with shadow %d\n", cur, MEM2SHADOW(cur), |
+ shadow); |
+ if (shadow != 0 && (shadow < 0 || SHADOW_OFFSET(cur) >= shadow)) { |
+ __asan_error(ptr, size); |
+ } |
+ } |
+} |
+ |
+void __asan_check_load(char *ptr, int size) { |
+ // aligned single word accesses may be widened single byte accesses, but for |
+ // all else use strict check |
+ bool strict = !((uintptr_t)ptr % WORD_SIZE == 0 && size == WORD_SIZE); |
+ __asan_check(ptr, size, strict); |
+} |
+ |
+void __asan_check_store(char *ptr, int size) { |
+ // stores may never be partially out of bounds so use strict check |
+ bool strict = true; |
+ __asan_check(ptr, size, strict); |
+} |
+ |
void __asan_init(int n_rzs, void **rzs, int *rz_sizes) { |
// ensure the redzones are large enough to hold metadata |
assert(RZ_SIZE >= sizeof(void *) && RZ_SIZE >= sizeof(size_t)); |
@@ -80,19 +119,6 @@ void __asan_init(int n_rzs, void **rzs, int *rz_sizes) { |
} |
} |
-void __asan_check(char *ptr, int size) { |
- printf("check %d bytes at %p\n", size, ptr); |
- char *end = ptr + size; |
- for (; ptr < end; ++ptr) { |
- char shadow = *(char *)MEM2SHADOW(ptr); |
- printf("checking %p with shadow %d\n", ptr, shadow); |
- if (shadow != 0 && (shadow < 0 || SHADOW_OFFSET(ptr) > shadow)) { |
- fprintf(stderr, "Illegal access of %d bytes at %p\n", size, ptr); |
- abort(); |
- } |
- } |
-} |
- |
void *__asan_malloc(size_t size) { |
printf("malloc() called with size %d\n", size); |
size_t padding = |