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

Unified Diff: runtime/szrt_asan.c

Issue 2211733002: Subzero: Improved quality of ASan error messages (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Replaced switch statements with table lookups 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | src/IceASanInstrumentation.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/szrt_asan.c
diff --git a/runtime/szrt_asan.c b/runtime/szrt_asan.c
index b1cf9d1dd524d305a7818d5e64544d0b668ced85..8600ed5ddf86253b0c6486b648635416fb87f544 100644
--- a/runtime/szrt_asan.c
+++ b/runtime/szrt_asan.c
@@ -44,7 +44,15 @@
#define SHADOW2MEM(p) \
((uintptr_t)((char *)(p)-shadow_offset) << SHADOW_SCALE_LOG2)
-#define POISON_VAL (-1)
+#define STACK_POISON_VAL ((char)-1)
+#define HEAP_POISON_VAL ((char)-2)
+#define GLOBAL_POISON_VAL ((char)-3)
+#define MEMTYPE_INDEX(x) (-1 - (x))
+static const char *memtype_names[] = {"stack", "heap", "global"};
+
+#define ACCESS_LOAD (0)
+#define ACCESS_STORE (1)
+static const char *access_names[] = {"load from", "store to"};
#if DEBUG
#define DUMP(args...) \
@@ -57,8 +65,8 @@
static char *shadow_offset = NULL;
-static void __asan_error(char *, int);
-static void __asan_check(char *, int);
+static bool __asan_check(char *, int);
+static void __asan_error(char *, int, int);
static void __asan_get_redzones(char *, char **, char **);
void __asan_init(int, void **, int *);
@@ -68,27 +76,35 @@ void *__asan_malloc(size_t);
void *__asan_calloc(size_t, size_t);
void *__asan_realloc(char *, size_t);
void __asan_free(char *);
-void __asan_poison(char *, int);
+void __asan_poison(char *, int, char);
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);
+static void __asan_error(char *ptr, int size, int access) {
+ char *shadow_addr = MEM2SHADOW(ptr);
+ char shadow_val = *shadow_addr;
+ if (shadow_val > 0)
+ shadow_val = *(shadow_addr + 1);
+ assert(access == ACCESS_LOAD || access == ACCESS_STORE);
+ const char *access_name = access_names[access];
+ assert(shadow_val == STACK_POISON_VAL || shadow_val == HEAP_POISON_VAL ||
+ shadow_val == GLOBAL_POISON_VAL);
+ const char *memtype = memtype_names[MEMTYPE_INDEX(shadow_val)];
+ fprintf(stderr, "Illegal %d byte %s %s object at %p\n", size, access_name,
+ memtype, ptr);
abort();
}
// check only the first byte of each word unless strict
-static void __asan_check(char *ptr, int size) {
+static bool __asan_check(char *ptr, int size) {
assert(size == 1 || size == 2 || size == 4 || size == 8);
char *shadow_addr = (char *)MEM2SHADOW(ptr);
+ char shadow_val = *shadow_addr;
DUMP("check %d bytes at %p: %p + %d (%d)\n", size, ptr, shadow_addr,
- (uintptr_t)ptr % SHADOW_SCALE, *shadow_addr);
+ (uintptr_t)ptr % SHADOW_SCALE, shadow_val);
if (size == SHADOW_SCALE) {
- if (*shadow_addr != 0)
- __asan_error(ptr, size);
- return;
+ return shadow_val == 0;
}
- if (*shadow_addr != 0 && (char)SHADOW_OFFSET(ptr) + size > *shadow_addr)
- __asan_error(ptr, size);
+ return shadow_val == 0 || (char)SHADOW_OFFSET(ptr) + size <= shadow_val;
}
static void __asan_get_redzones(char *ptr, char **left, char **right) {
@@ -103,15 +119,16 @@ static void __asan_get_redzones(char *ptr, char **left, char **right) {
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
- if (size == WORD_SIZE && (uintptr_t)ptr % WORD_SIZE == 0)
- size = 1;
- __asan_check(ptr, size);
+ int check_size =
+ (size == WORD_SIZE && (uintptr_t)ptr % WORD_SIZE == 0) ? 1 : size;
+ if (!__asan_check(ptr, check_size))
+ __asan_error(ptr, size, ACCESS_LOAD);
}
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);
+ if (!__asan_check(ptr, size))
+ __asan_error(ptr, size, ACCESS_STORE);
}
void __asan_init(int n_rzs, void **rzs, int *rz_sizes) {
@@ -138,7 +155,7 @@ void __asan_init(int n_rzs, void **rzs, int *rz_sizes) {
DUMP("poisioning %d global redzones\n", n_rzs);
for (int i = 0; i < n_rzs; i++) {
DUMP("(%d) poisoning redzone of size %d at %p\n", i, rz_sizes[i], rzs[i]);
- __asan_poison(rzs[i], rz_sizes[i]);
+ __asan_poison(rzs[i], rz_sizes[i], GLOBAL_POISON_VAL);
}
}
@@ -157,8 +174,8 @@ void *__asan_malloc(size_t size) {
}
void *ret = rz_left + rz_left_size;
void *rz_right = ret + size;
- __asan_poison(rz_left, rz_left_size);
- __asan_poison(rz_right, rz_right_size);
+ __asan_poison(rz_left, rz_left_size, HEAP_POISON_VAL);
+ __asan_poison(rz_right, rz_right_size, HEAP_POISON_VAL);
// record size and location data so we can find it again
*(void **)rz_left = rz_right;
*(size_t *)rz_right = rz_right_size;
@@ -204,7 +221,7 @@ void __asan_free(char *ptr) {
free(rz_left);
}
-void __asan_poison(char *ptr, int size) {
+void __asan_poison(char *ptr, int size, char poison_val) {
char *end = ptr + size;
assert(IS_SHADOW_ALIGNED(end));
// redzones should be no greater than RZ_SIZE + RZ_SIZE-1 for alignment
@@ -212,12 +229,11 @@ void __asan_poison(char *ptr, int size) {
DUMP("poison %d bytes at %p: %p - %p\n", size, ptr, MEM2SHADOW(ptr),
MEM2SHADOW(end));
size_t offset = SHADOW_OFFSET(ptr);
- *(char *)MEM2SHADOW(ptr) = (offset == 0) ? POISON_VAL : offset;
+ *(char *)MEM2SHADOW(ptr) = (offset == 0) ? poison_val : offset;
ptr += SHADOW_OFFSET(size);
assert(IS_SHADOW_ALIGNED(ptr));
- for (; ptr != end; ptr += SHADOW_SCALE) {
- *(char *)MEM2SHADOW(ptr) = POISON_VAL;
- }
+ int len = (end - ptr) >> SHADOW_SCALE_LOG2;
+ memset(MEM2SHADOW(ptr), poison_val, len);
}
void __asan_unpoison(char *ptr, int size) {
@@ -229,7 +245,5 @@ void __asan_unpoison(char *ptr, int size) {
*(char *)MEM2SHADOW(ptr) = 0;
ptr += SHADOW_OFFSET(size);
assert(IS_SHADOW_ALIGNED(ptr));
- for (; ptr != end; ptr += SHADOW_SCALE) {
- *(char *)MEM2SHADOW(ptr) = 0;
- }
+ memset(MEM2SHADOW(ptr), 0, (end - ptr) >> SHADOW_SCALE_LOG2);
}
« no previous file with comments | « no previous file | src/IceASanInstrumentation.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698