aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/hwasan/hwasan_allocator.cc14
-rw-r--r--test/hwasan/TestCases/tag_in_free.c51
2 files changed, 61 insertions, 4 deletions
diff --git a/lib/hwasan/hwasan_allocator.cc b/lib/hwasan/hwasan_allocator.cc
index dc56bd7ef..4a4de3e45 100644
--- a/lib/hwasan/hwasan_allocator.cc
+++ b/lib/hwasan/hwasan_allocator.cc
@@ -176,10 +176,16 @@ static void *HwasanAllocate(StackTrace *stack, uptr orig_size, uptr alignment,
size - orig_size);
void *user_ptr = allocated;
- if (flags()->tag_in_malloc &&
- atomic_load_relaxed(&hwasan_allocator_tagging_enabled))
- user_ptr = (void *)TagMemoryAligned(
- (uptr)user_ptr, size, t ? t->GenerateRandomTag() : kFallbackAllocTag);
+ // Tagging can only be skipped when both tag_in_malloc and tag_in_free are
+ // false. When tag_in_malloc = false and tag_in_free = true malloc needs to
+ // retag to 0.
+ if ((flags()->tag_in_malloc || flags()->tag_in_free) &&
+ atomic_load_relaxed(&hwasan_allocator_tagging_enabled)) {
+ tag_t tag = flags()->tag_in_malloc
+ ? (t ? t->GenerateRandomTag() : kFallbackAllocTag)
+ : 0;
+ user_ptr = (void *)TagMemoryAligned((uptr)user_ptr, size, tag);
+ }
if ((orig_size % kShadowAlignment) && (alignment <= kShadowAlignment) &&
right_align_mode) {
diff --git a/test/hwasan/TestCases/tag_in_free.c b/test/hwasan/TestCases/tag_in_free.c
new file mode 100644
index 000000000..51e8d015d
--- /dev/null
+++ b/test/hwasan/TestCases/tag_in_free.c
@@ -0,0 +1,51 @@
+// RUN: %clang_hwasan -O0 %s -DMALLOC -DFREE -o %t.mf
+// RUN: %env_hwasan_opts=tag_in_malloc=0,tag_in_free=1 not %run %t.mf 2>&1 | FileCheck %s --check-prefixes=FREE
+// RUN: %env_hwasan_opts=tag_in_malloc=1,tag_in_free=1 not %run %t.mf 2>&1 | FileCheck %s --check-prefixes=MALLOC
+// RUN: %env_hwasan_opts=tag_in_malloc=1,tag_in_free=0 not %run %t.mf 2>&1 | FileCheck %s --check-prefixes=MALLOC
+// RUN: %env_hwasan_opts=tag_in_malloc=0,tag_in_free=0 %run %t.mf 2>&1
+
+// RUN: %clang_hwasan -O0 %s -DFREE -o %t.f
+// RUN: %env_hwasan_opts=tag_in_malloc=0,tag_in_free=1 not %run %t.f 2>&1 | FileCheck %s --check-prefixes=FREE
+// RUN: %env_hwasan_opts=tag_in_malloc=1,tag_in_free=1 not %run %t.f 2>&1 | FileCheck %s --check-prefixes=FREE
+// RUN: %env_hwasan_opts=tag_in_malloc=1,tag_in_free=0 %run %t.f 2>&1
+// RUN: %env_hwasan_opts=tag_in_malloc=0,tag_in_free=0 %run %t.f 2>&1
+
+// RUN: %clang_hwasan -O0 %s -DMALLOC -o %t.m
+// RUN: %env_hwasan_opts=tag_in_malloc=0,tag_in_free=1 %run %t.m 2>&1
+// RUN: %env_hwasan_opts=tag_in_malloc=1,tag_in_free=1 not %run %t.m 2>&1 | FileCheck %s --check-prefixes=MALLOC
+// RUN: %env_hwasan_opts=tag_in_malloc=1,tag_in_free=0 not %run %t.m 2>&1 | FileCheck %s --check-prefixes=MALLOC
+// RUN: %env_hwasan_opts=tag_in_malloc=0,tag_in_free=0 %run %t.m 2>&1
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sanitizer/hwasan_interface.h>
+
+int main() {
+ __hwasan_enable_allocator_tagging();
+ // Loop for a while to make sure that the memory for the test below is reused after an earlier free(),
+ // and is potentially tagged (when tag_in_free == 1).
+ for (int i = 0; i < 100; ++i) {
+ char * volatile p = (char*)malloc(10);
+ free(p);
+ }
+
+ char * volatile p = (char*)malloc(10);
+#ifdef MALLOC
+ // MALLOC: READ of size 1 at
+ // MALLOC: is located 6 bytes to the right of 10-byte region
+ // MALLOC: allocated here:
+ char volatile x = p[16];
+#endif
+ free(p);
+#ifdef FREE
+ // FREE: READ of size 1 at
+ // FREE: is located 0 bytes inside of 10-byte region
+ // FREE: freed by thread T0 here:
+ // FREE: previously allocated here:
+ char volatile y = p[0];
+#endif
+
+ __hwasan_disable_allocator_tagging();
+
+ return 0;
+}