1 | // RUN: %clangxx_asan -O0 %s -o %t -mllvm -asan-detect-invalid-pointer-pair |
2 | |
3 | // RUN: %env_asan_opts=detect_invalid_pointer_pairs=1 %run %t k 2>&1 | FileCheck %s -check-prefix=OK -allow-empty |
4 | // RUN: %env_asan_opts=detect_invalid_pointer_pairs=1 not %run %t g 2>&1 | FileCheck %s -check-prefix=CMP -check-prefix=ALL-ERRORS |
5 | // RUN: %env_asan_opts=detect_invalid_pointer_pairs=1 not %run %t s 2>&1 | FileCheck %s -check-prefix=SUB -check-prefix=ALL-ERRORS |
6 | // RUN: %env_asan_opts=detect_invalid_pointer_pairs=1 not %run %t f 2>&1 | FileCheck %s -check-prefix=FREE -check-prefix=ALL-ERRORS |
7 | |
8 | #include <assert.h> |
9 | #include <stdlib.h> |
10 | |
11 | int f(char c, char *p, char *q) { |
12 | // ALL-ERRORS: ERROR: AddressSanitizer: invalid-pointer-pair |
13 | // [[PTR1:0x[0-9a-f]+]] [[PTR2:0x[0-9a-f]+]] |
14 | switch (c) { |
15 | case 'g': |
16 | // CMP: #{{[0-9]+ .*}} in f({{char, *char *\*, *char *\*}}) {{.*}}invalid-pointer-pairs.cpp:[[@LINE+1]] |
17 | return p > q; |
18 | case 's': |
19 | // SUB: #{{[0-9]+ .*}} in f({{char, *char *\*, *char *\*}}) {{.*}}invalid-pointer-pairs.cpp:[[@LINE+1]] |
20 | return p - q; |
21 | case 'k': { |
22 | // OK-NOT: ERROR |
23 | char *p2 = p + 20; |
24 | return p > p2; |
25 | } |
26 | case 'f': { |
27 | char *p3 = p + 20; |
28 | free(ptr: p); |
29 | // FREE: #{{[0-9]+ .*}} in f({{char, *char *\*, *char *\*}}) {{.*}}invalid-pointer-pairs.cpp:[[@LINE+2]] |
30 | // FREE: freed by thread |
31 | return p < p3; |
32 | } |
33 | } |
34 | assert(0); |
35 | } |
36 | |
37 | int main(int argc, char **argv) { |
38 | char *p = (char *)malloc(size: 42); |
39 | char *q = (char *)malloc(size: 42); |
40 | assert(argc >= 2); |
41 | f(c: argv[1][0], p, q); |
42 | free(ptr: p); |
43 | free(ptr: q); |
44 | } |
45 | |