xref: /llvm-project/compiler-rt/test/hwasan/TestCases/use-after-free-and-overflow.c (revision fdac98a7f3bbe0cb553df60df8cca2e8f407fa51)
1 // Checks that we do not print a faraway buffer overrun if we find a
2 // use-after-free.
3 // RUN: %clang_hwasan -O0 %s -o %t
4 // RUN: not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK
5 
6 #include <sanitizer/hwasan_interface.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 
10 #define ALLOC_ATTEMPTS 256
11 
Untag(void * x)12 char *Untag(void *x) {
13   return (char *)__hwasan_tag_pointer(x, 0);
14 }
15 
FindMatch(void * ptrs[ALLOC_ATTEMPTS],void * value)16 void *FindMatch(void *ptrs[ALLOC_ATTEMPTS], void *value) {
17   for (int i = 0; i < ALLOC_ATTEMPTS; ++i) {
18     if (!ptrs[i])
19       return NULL;
20     int distance = Untag(value) - Untag(ptrs[i]);
21     // Leave at least one granule of gap to the allocation.
22     if (abs(distance) < 1000 && abs(distance) > 32)
23       return ptrs[i];
24   }
25   return NULL;
26 }
27 
main(int argc,char ** argv)28 int main(int argc, char **argv) {
29   __hwasan_enable_allocator_tagging();
30   void *ptrs[ALLOC_ATTEMPTS] = {};
31   // Find two allocations that are close enough so that they would be
32   // candidates as buffer overflows for each other.
33   void *one;
34   void *other;
35   for (int i = 0; i < ALLOC_ATTEMPTS; ++i) {
36     one = malloc(16);
37     other = FindMatch(ptrs, one);
38     ptrs[i] = one;
39     if (other)
40       break;
41   }
42   if (!other) {
43     fprintf(stderr, "Could not find closeby allocations.\n");
44     abort();
45   }
46   __hwasan_tag_memory(Untag(one), 3, 16);
47   __hwasan_tag_memory(Untag(other), 3, 16);
48   // Tag potential adjaceant allocations with a mismatching tag, otherwise this
49   // test would flake.
50   __hwasan_tag_memory(Untag(one) + 16, 4, 16);
51   __hwasan_tag_memory(Untag(one) - 16, 4, 16);
52   void *retagged_one = __hwasan_tag_pointer(one, 3);
53   free(retagged_one);
54   volatile char *ptr = (char *)retagged_one;
55   *ptr = 1;
56 }
57 
58 // CHECK-NOT: Cause: heap-buffer-overflow
59 // CHECK: Cause: use-after-free
60 // CHECK-NOT: Cause: heap-buffer-overflow
61