summaryrefslogtreecommitdiff
path: root/test/hwasan
diff options
context:
space:
mode:
Diffstat (limited to 'test/hwasan')
-rw-r--r--test/hwasan/TestCases/abort-message-android.cc28
-rw-r--r--test/hwasan/TestCases/cfi.cc18
-rw-r--r--test/hwasan/TestCases/heap-buffer-overflow.c45
-rw-r--r--test/hwasan/TestCases/random-align-right.c35
-rw-r--r--test/hwasan/TestCases/stack-history-length.c10
-rw-r--r--test/hwasan/TestCases/stack-uar.c36
-rw-r--r--test/hwasan/TestCases/tail-magic.c28
-rw-r--r--test/hwasan/TestCases/thread-uaf.c2
-rw-r--r--test/hwasan/TestCases/use-after-free.c9
9 files changed, 189 insertions, 22 deletions
diff --git a/test/hwasan/TestCases/abort-message-android.cc b/test/hwasan/TestCases/abort-message-android.cc
new file mode 100644
index 000000000..f89b929d4
--- /dev/null
+++ b/test/hwasan/TestCases/abort-message-android.cc
@@ -0,0 +1,28 @@
+// RUN: %clangxx_hwasan -DERR=1 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_hwasan -DERR=2 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// REQUIRES: android
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <sanitizer/hwasan_interface.h>
+
+__attribute__((no_sanitize("hwaddress")))
+extern "C" void android_set_abort_message(const char *msg) {
+ fprintf(stderr, "== abort message start\n%s\n== abort message end\n", msg);
+}
+
+int main() {
+ __hwasan_enable_allocator_tagging();
+ char *volatile p = (char *)malloc(16);
+ if (ERR==1) {
+ p[16] = 1;
+ } else {
+ free(p);
+ free(p);
+ }
+ // CHECK: ERROR: HWAddressSanitizer:
+ // CHECK: == abort message start
+ // CHECK: ERROR: HWAddressSanitizer:
+ // CHECK: == abort message end
+}
diff --git a/test/hwasan/TestCases/cfi.cc b/test/hwasan/TestCases/cfi.cc
new file mode 100644
index 000000000..457e29659
--- /dev/null
+++ b/test/hwasan/TestCases/cfi.cc
@@ -0,0 +1,18 @@
+// RUN: %clang_hwasan -fsanitize=cfi -fno-sanitize-trap=cfi -flto -fvisibility=hidden -fuse-ld=lld %s -o %t
+// RUN: not %run %t 2>&1 | FileCheck %s
+
+// REQUIRES: android
+
+// Smoke test for CFI + HWASAN.
+
+struct A {
+ virtual void f();
+};
+
+void A::f() {}
+
+int main() {
+ // CHECK: control flow integrity check for type {{.*}} failed during cast to unrelated type
+ A *a = reinterpret_cast<A *>(reinterpret_cast<void *>(&main));
+ (void)a;
+}
diff --git a/test/hwasan/TestCases/heap-buffer-overflow.c b/test/hwasan/TestCases/heap-buffer-overflow.c
index 40b6e6e9d..bff39d293 100644
--- a/test/hwasan/TestCases/heap-buffer-overflow.c
+++ b/test/hwasan/TestCases/heap-buffer-overflow.c
@@ -1,26 +1,61 @@
// RUN: %clang_hwasan %s -o %t
-// RUN: not %run %t 40 2>&1 | FileCheck %s --check-prefix=CHECK40
-// RUN: not %run %t 80 2>&1 | FileCheck %s --check-prefix=CHECK80
+// RUN: not %run %t 40 2>&1 | FileCheck %s --check-prefix=CHECK40-LEFT
+// RUN: %env_hwasan_opts=malloc_align_right=2 not %run %t 40 2>&1 | FileCheck %s --check-prefix=CHECK40-RIGHT
+// RUN: not %run %t 80 2>&1 | FileCheck %s --check-prefix=CHECK80-LEFT
+// RUN: %env_hwasan_opts=malloc_align_right=2 not %run %t 80 2>&1 | FileCheck %s --check-prefix=CHECK80-RIGHT
// RUN: not %run %t -30 2>&1 | FileCheck %s --check-prefix=CHECKm30
// RUN: not %run %t -30 1000000 2>&1 | FileCheck %s --check-prefix=CHECKMm30
// RUN: not %run %t 1000000 1000000 2>&1 | FileCheck %s --check-prefix=CHECKM
+// Test OOB within the granule.
+// Misses the bug when malloc is left-aligned, catches it otherwise.
+// RUN: %run %t 31
+// RUN: %env_hwasan_opts=malloc_align_right=2 not %run %t 31 2>&1 | FileCheck %s --check-prefix=CHECK31
+
+// RUN: %run %t 30 20
+// RUN: %env_hwasan_opts=malloc_align_right=9 not %run %t 30 20 2>&1 | FileCheck %s --check-prefix=CHECK20-RIGHT8
+
+// RUN: %env_hwasan_opts=malloc_align_right=42 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-WRONG-FLAG
+
// REQUIRES: stable-runtime
#include <stdlib.h>
#include <stdio.h>
#include <sanitizer/hwasan_interface.h>
+static volatile char sink;
+
int main(int argc, char **argv) {
__hwasan_enable_allocator_tagging();
int offset = argc < 2 ? 40 : atoi(argv[1]);
int size = argc < 3 ? 30 : atoi(argv[2]);
char * volatile x = (char*)malloc(size);
- x[offset] = 42;
-// CHECK40: is located 10 bytes to the right of 30-byte region
-// CHECK80: is located 50 bytes to the right of 30-byte region
+ fprintf(stderr, "base: %p access: %p\n", x, &x[offset]);
+ sink = x[offset];
+
+// CHECK40-LEFT: allocated heap chunk; size: 32 offset: 8
+// CHECK40-LEFT: is located 10 bytes to the right of 30-byte region
+// CHECK40-RIGHT: allocated heap chunk; size: 32 offset:
+// CHECK40-RIGHT: is located 10 bytes to the right of 30-byte region
+//
+// CHECK80-LEFT: allocated heap chunk; size: 32 offset: 16
+// CHECK80-LEFT: is located 50 bytes to the right of 30-byte region
+// CHECK80-RIGHT: allocated heap chunk; size: 32 offset:
+// CHECK80-RIGHT: is located 50 bytes to the right of 30-byte region
+//
+// CHECKm30: allocated heap chunk; size: 32 offset: 2
// CHECKm30: is located 30 bytes to the left of 30-byte region
+//
+// CHECKMm30: is a large allocated heap chunk; size: 1003520 offset: -30
// CHECKMm30: is located 30 bytes to the left of 1000000-byte region
+//
+// CHECKM: is a large allocated heap chunk; size: 1003520 offset: 1000000
// CHECKM: is located 0 bytes to the right of 1000000-byte region
+//
+// CHECK31: is located 1 bytes to the right of 30-byte region
+//
+// CHECK20-RIGHT8: is located 10 bytes to the right of 20-byte region [0x{{.*}}8,0x{{.*}}c)
+//
+// CHECK-WRONG-FLAG: ERROR: unsupported value of malloc_align_right flag: 42
free(x);
}
diff --git a/test/hwasan/TestCases/random-align-right.c b/test/hwasan/TestCases/random-align-right.c
new file mode 100644
index 000000000..8c524ef47
--- /dev/null
+++ b/test/hwasan/TestCases/random-align-right.c
@@ -0,0 +1,35 @@
+// Tests malloc_align_right=1 and 8 (randomly aligning right).
+// RUN: %clang_hwasan %s -o %t
+//
+// RUN: %run %t
+// RUN: %env_hwasan_opts=malloc_align_right=1 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK1
+// RUN: %env_hwasan_opts=malloc_align_right=8 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK8
+
+// REQUIRES: stable-runtime
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sanitizer/hwasan_interface.h>
+
+static volatile void *sink;
+
+int main(int argc, char **argv) {
+ __hwasan_enable_allocator_tagging();
+
+ // Perform 1000 buffer overflows within the 16-byte granule,
+ // so that random right-alignment has a very high chance of
+ // catching at least one of them.
+ for (int i = 0; i < 1000; i++) {
+ char *p = (char*)malloc(20);
+ sink = p;
+ fprintf(stderr, "[%d] p: %p; accessing p[20]:\n", i, p);
+ p[20 * argc] = 0; // requires malloc_align_right=1 to catch
+ fprintf(stderr, "[%d] p: %p; accessing p[30]:\n", i, p);
+ p[30 * argc] = 0; // requires malloc_align_right={1,8} to catch
+// CHECK1: accessing p[20]
+// CHECK1-NEXT: HWAddressSanitizer: tag-mismatch
+// CHECK8: accessing p[30]:
+// CHECK8-NEXT: HWAddressSanitizer: tag-mismatch
+ }
+}
+
diff --git a/test/hwasan/TestCases/stack-history-length.c b/test/hwasan/TestCases/stack-history-length.c
index f4c0b036f..c8583c67c 100644
--- a/test/hwasan/TestCases/stack-history-length.c
+++ b/test/hwasan/TestCases/stack-history-length.c
@@ -1,7 +1,6 @@
-// RUN: %clang_hwasan -O1 -DX=2046 %s -o %t.2046
-// RUN: %clang_hwasan -O1 -DX=2047 %s -o %t.2047
-// RUN: %env_hwasan_opts=stack_history_size=2048 not %run %t.2046 2>&1 | FileCheck %s --check-prefix=YES
-// RUN: %env_hwasan_opts=stack_history_size=2048 not %run %t.2047 2>&1 | FileCheck %s --check-prefix=NO
+// RUN: %clang_hwasan -O1 %s -o %t
+// RUN: %env_hwasan_opts=stack_history_size=2048 not %run %t 2046 2>&1 | FileCheck %s --check-prefix=YES
+// RUN: %env_hwasan_opts=stack_history_size=2048 not %run %t 2047 2>&1 | FileCheck %s --check-prefix=NO
// REQUIRES: stable-runtime
@@ -16,7 +15,8 @@ __attribute__((noinline)) void FUNC0() { int x[4]; USE(&x[0]); }
__attribute__((noinline)) void FUNC() { int x[4]; USE(&x[0]); }
__attribute__((noinline)) void OOB() { int x[4]; x[four] = 0; USE(&x[0]); }
-int main() {
+int main(int argc, char **argv) {
+ int X = argc == 2 ? atoi(argv[1]) : 10;
// FUNC0 is X+2's element of the ring buffer.
// If runtime buffer size is less than it, FUNC0 record will be lost.
FUNC0();
diff --git a/test/hwasan/TestCases/stack-uar.c b/test/hwasan/TestCases/stack-uar.c
index 2c59b1785..0b1faf8b5 100644
--- a/test/hwasan/TestCases/stack-uar.c
+++ b/test/hwasan/TestCases/stack-uar.c
@@ -1,23 +1,41 @@
-// RUN: %clang_hwasan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// Tests use-after-return detection and reporting.
+// RUN: %clang_hwasan -O0 -fno-discard-value-names %s -o %t && not %run %t 2>&1 | FileCheck %s
// REQUIRES: stable-runtime
-#include <stdlib.h>
-#include <sanitizer/hwasan_interface.h>
+void USE(void *x) { // pretend_to_do_something(void *x)
+ __asm__ __volatile__("" : : "r" (x) : "memory");
+}
__attribute__((noinline))
-char *f() {
- char z[0x1000];
- char *volatile p = z;
+char *buggy() {
+ char zzz[0x1000];
+ char *volatile p = zzz;
return p;
}
+__attribute__((noinline)) void Unrelated1() { int A[2]; USE(&A[0]); }
+__attribute__((noinline)) void Unrelated2() { int BB[3]; USE(&BB[0]); }
+__attribute__((noinline)) void Unrelated3() { int CCC[4]; USE(&CCC[0]); }
+
int main() {
- return *f();
+ char *p = buggy();
+ Unrelated1();
+ Unrelated2();
+ Unrelated3();
+ return *p;
// CHECK: READ of size 1 at
- // CHECK: #0 {{.*}} in main{{.*}}stack-uar.c:16
-
+ // CHECK: #0 {{.*}} in main{{.*}}stack-uar.c:[[@LINE-2]]
// CHECK: is located in stack of thread
+ // CHECK: Previosly allocated frames:
+ // CHECK: Unrelated3
+ // CHECK: 16 CCC
+ // CHECK: Unrelated2
+ // CHECK: 12 BB
+ // CHECK: Unrelated1
+ // CHECK: 8 A
+ // CHECK: buggy
+ // CHECK: 4096 zzz
// CHECK: SUMMARY: HWAddressSanitizer: tag-mismatch {{.*}} in main
}
diff --git a/test/hwasan/TestCases/tail-magic.c b/test/hwasan/TestCases/tail-magic.c
new file mode 100644
index 000000000..95c5ada08
--- /dev/null
+++ b/test/hwasan/TestCases/tail-magic.c
@@ -0,0 +1,28 @@
+// Tests free_checks_tail_magic=1.
+// RUN: %clang_hwasan %s -o %t
+// RUN: %env_hwasan_opts=free_checks_tail_magic=0 %run %t
+// RUN: %env_hwasan_opts=free_checks_tail_magic=1 not %run %t 2>&1 | FileCheck %s
+// RUN: not %run %t 2>&1 | FileCheck %s
+
+// REQUIRES: stable-runtime
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sanitizer/hwasan_interface.h>
+
+static volatile void *sink;
+
+int main(int argc, char **argv) {
+ __hwasan_enable_allocator_tagging();
+
+ char *p = (char*)malloc(20);
+ sink = p;
+ p[20] = 0x42;
+ p[24] = 0x66;
+ free(p);
+// CHECK: ERROR: HWAddressSanitizer: alocation-tail-overwritten; heap object [{{.*}}) of size 20
+// CHECK: in main {{.*}}tail-magic.c:[[@LINE-2]]
+// CHECK: allocated here:
+// CHECK: in main {{.*}}tail-magic.c:[[@LINE-8]]
+// CHECK: Tail contains: .. .. .. .. 42 {{.. .. ..}} 66
+}
diff --git a/test/hwasan/TestCases/thread-uaf.c b/test/hwasan/TestCases/thread-uaf.c
index 33cea1018..f091167e3 100644
--- a/test/hwasan/TestCases/thread-uaf.c
+++ b/test/hwasan/TestCases/thread-uaf.c
@@ -36,6 +36,8 @@ void *Use(void *arg) {
// CHECK: in Allocate
// CHECK: Thread: T2 0x
// CHECK: Thread: T3 0x
+ // CHECK-DAG: Thread: T0 0x
+ // CHECK-DAG: Thread: T1 0x
__sync_fetch_and_add(&state, 1);
return NULL;
}
diff --git a/test/hwasan/TestCases/use-after-free.c b/test/hwasan/TestCases/use-after-free.c
index 3dae97b0c..fcdd0771c 100644
--- a/test/hwasan/TestCases/use-after-free.c
+++ b/test/hwasan/TestCases/use-after-free.c
@@ -22,14 +22,17 @@ int main() {
if (ISREAD) r = x[5]; else x[5] = 42; // should be on the same line.
// CHECK: [[TYPE]] of size 1 at {{.*}} tags: [[PTR_TAG:[0-9a-f][0-9a-f]]]/[[MEM_TAG:[0-9a-f][0-9a-f]]] (ptr/mem)
// CHECK: #0 {{.*}} in main {{.*}}use-after-free.c:[[@LINE-2]]
-
+ // Offset is 5 or 11 depending on left/right alignment.
+ // CHECK: is a small unallocated heap chunk; size: 16 offset: {{5|11}}
+ // CHECK: is located 5 bytes inside of 10-byte region
+ //
// CHECK: freed by thread {{.*}} here:
// CHECK: #0 {{.*}} in {{.*}}free{{.*}} {{.*}}hwasan_interceptors.cc
- // CHECK: #1 {{.*}} in main {{.*}}use-after-free.c:[[@LINE-11]]
+ // CHECK: #1 {{.*}} in main {{.*}}use-after-free.c:[[@LINE-14]]
// CHECK: previously allocated here:
// CHECK: #0 {{.*}} in {{.*}}malloc{{.*}} {{.*}}hwasan_interceptors.cc
- // CHECK: #1 {{.*}} in main {{.*}}use-after-free.c:[[@LINE-16]]
+ // CHECK: #1 {{.*}} in main {{.*}}use-after-free.c:[[@LINE-19]]
// CHECK: Memory tags around the buggy address (one tag corresponds to 16 bytes):
// CHECK: =>{{.*}}[[MEM_TAG]]
// CHECK: SUMMARY: HWAddressSanitizer: tag-mismatch {{.*}} in main