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 | |
12 | char *Untag(void *x) { |
13 | return (char *)__hwasan_tag_pointer(p: x, tag: 0); |
14 | } |
15 | |
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(x: value) - Untag(x: ptrs[i]); |
21 | // Leave at least one granule of gap to the allocation. |
22 | if (abs(x: distance) < 1000 && abs(x: distance) > 32) |
23 | return ptrs[i]; |
24 | } |
25 | return NULL; |
26 | } |
27 | |
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(size: 16); |
37 | other = FindMatch(ptrs, value: one); |
38 | ptrs[i] = one; |
39 | if (other) |
40 | break; |
41 | } |
42 | if (!other) { |
43 | fprintf(stderr, format: "Could not find closeby allocations.\n" ); |
44 | abort(); |
45 | } |
46 | __hwasan_tag_memory(p: Untag(x: one), tag: 3, size: 16); |
47 | __hwasan_tag_memory(p: Untag(x: other), tag: 3, size: 16); |
48 | // Tag potential adjaceant allocations with a mismatching tag, otherwise this |
49 | // test would flake. |
50 | __hwasan_tag_memory(p: Untag(x: one) + 16, tag: 4, size: 16); |
51 | __hwasan_tag_memory(p: Untag(x: one) - 16, tag: 4, size: 16); |
52 | void *retagged_one = __hwasan_tag_pointer(p: one, tag: 3); |
53 | free(ptr: 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 | |