xref: /llvm-project/compiler-rt/test/hwasan/TestCases/thread-uaf.c (revision fdac98a7f3bbe0cb553df60df8cca2e8f407fa51)
1 // Tests UAF detection where Allocate/Deallocate/Use
2 // happen in separate threads.
3 // RUN: %clang_hwasan %s -o %t && not %run %t 2>&1 | FileCheck %s
4 
5 #include <pthread.h>
6 #include <stdlib.h>
7 #include <stdio.h>
8 
9 #include <sanitizer/hwasan_interface.h>
10 
11 char *volatile x;
12 int state;
13 
Allocate(void * arg)14 void *Allocate(void *arg) {
15   x = (char*)malloc(10);
16   __sync_fetch_and_add(&state, 1);
17   while (__sync_fetch_and_add(&state, 0) != 3) {}
18   return NULL;
19 }
Deallocate(void * arg)20 void *Deallocate(void *arg) {
21   free(x);
22   __sync_fetch_and_add(&state, 1);
23   while (__sync_fetch_and_add(&state, 0) != 3) {}
24   return NULL;
25 }
26 
Use(void * arg)27 void *Use(void *arg) {
28   x[5] = 42;
29   // CHECK: ERROR: HWAddressSanitizer: tag-mismatch on address
30   // CHECK: WRITE of size 1 {{.*}} in thread T3
31   // CHECK: thread-uaf.c:[[@LINE-3]]
32   // CHECK: Cause: use-after-free
33   // CHECK: freed by thread T2 here
34   // CHECK: in Deallocate
35   // CHECK: previously allocated by thread T1 here:
36   // CHECK: in Allocate
37   // CHECK-DAG: Thread: T2 0x
38   // CHECK-DAG: Thread: T3 0x
39   // CHECK-DAG: Thread: T0 0x
40   // CHECK-DAG: Thread: T1 0x
41   __sync_fetch_and_add(&state, 1);
42   return NULL;
43 }
44 
main()45 int main() {
46   __hwasan_enable_allocator_tagging();
47   pthread_t t1, t2, t3;
48 
49   pthread_create(&t1, NULL, Allocate, NULL);
50   while (__sync_fetch_and_add(&state, 0) != 1) {}
51   pthread_create(&t2, NULL, Deallocate, NULL);
52   while (__sync_fetch_and_add(&state, 0) != 2) {}
53   pthread_create(&t3, NULL, Use, NULL);
54 
55   pthread_join(t1, NULL);
56   pthread_join(t2, NULL);
57   pthread_join(t3, NULL);
58 }
59