From 1ce8e22e8474d244b05bb842ef54e9d5af7188bc Mon Sep 17 00:00:00 2001 From: Alex Shlyapnikov Date: Mon, 4 Dec 2017 18:00:24 +0000 Subject: [ASan] Enhance libsanitizer support for invalid-pointer-pair. Following patch adds support of all memory origins in CheckForInvalidPointerPair function. For small difference of pointers, it's directly done in shadow memory (the limit was set to 2048B). Then we search for origin of first pointer and verify that the second one has the same origin. If so, we verify that it points either to a same variable (in case of stack memory or a global variable), or to a same heap segment. Committing on behanf of marxin and jakubjelinek. Reviewers: alekseyshl, kcc Subscribers: llvm-commits Differential revision: https://reviews.llvm.org/D40600 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@319668 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Posix/invalid-pointer-pairs-threads.cc | 54 +++++++++++ .../invalid-pointer-pairs-compare-errors.cc | 103 +++++++++++++++++++++ .../invalid-pointer-pairs-compare-success.cc | 74 +++++++++++++++ .../invalid-pointer-pairs-subtract-errors.cc | 48 ++++++++++ .../invalid-pointer-pairs-subtract-success.cc | 33 +++++++ 5 files changed, 312 insertions(+) create mode 100644 test/asan/TestCases/Posix/invalid-pointer-pairs-threads.cc create mode 100644 test/asan/TestCases/invalid-pointer-pairs-compare-errors.cc create mode 100644 test/asan/TestCases/invalid-pointer-pairs-compare-success.cc create mode 100644 test/asan/TestCases/invalid-pointer-pairs-subtract-errors.cc create mode 100644 test/asan/TestCases/invalid-pointer-pairs-subtract-success.cc (limited to 'test') diff --git a/test/asan/TestCases/Posix/invalid-pointer-pairs-threads.cc b/test/asan/TestCases/Posix/invalid-pointer-pairs-threads.cc new file mode 100644 index 000000000..db7f2b7fb --- /dev/null +++ b/test/asan/TestCases/Posix/invalid-pointer-pairs-threads.cc @@ -0,0 +1,54 @@ +// RUN: %clangxx_asan -O0 %s -o %t -mllvm -asan-detect-invalid-pointer-pair + +// RUN: %env_asan_opts=detect_invalid_pointer_pairs=1 %run %t a 2>&1 | FileCheck %s -check-prefix=OK -allow-empty +// RUN: %env_asan_opts=detect_invalid_pointer_pairs=1 not %run %t b 2>&1 | FileCheck %s -check-prefix=B + +#include +#include +#include +#include + +char *pointers[2]; +pthread_barrier_t bar; + +void *thread_main(void *n) { + char local; + + unsigned long id = (unsigned long)n; + pointers[id] = &local; + pthread_barrier_wait(&bar); + pthread_barrier_wait(&bar); + + return NULL; +} + +int main(int argc, char **argv) { + assert(argc >= 2); + + char t = argv[1][0]; + + pthread_t threads[2]; + pthread_barrier_init(&bar, NULL, 3); + pthread_create(&threads[0], 0, thread_main, (void *)0); + pthread_create(&threads[1], 0, thread_main, (void *)1); + pthread_barrier_wait(&bar); + + if (t == 'a') { + // OK-NOT: not handled yet + unsigned r = pointers[0] - pointers[1]; + } else { + char local; + char *parent_pointer = &local; + + // B: ERROR: AddressSanitizer: invalid-pointer-pair + // B: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-threads.cc:[[@LINE+1]] + unsigned r = parent_pointer - pointers[0]; + } + + pthread_barrier_wait(&bar); + pthread_join(threads[0], 0); + pthread_join(threads[1], 0); + pthread_barrier_destroy(&bar); + + return 0; +} diff --git a/test/asan/TestCases/invalid-pointer-pairs-compare-errors.cc b/test/asan/TestCases/invalid-pointer-pairs-compare-errors.cc new file mode 100644 index 000000000..82f63359e --- /dev/null +++ b/test/asan/TestCases/invalid-pointer-pairs-compare-errors.cc @@ -0,0 +1,103 @@ +// RUN: %clangxx_asan -O0 %s -o %t -mllvm -asan-detect-invalid-pointer-pair + +// RUN: %env_asan_opts=detect_invalid_pointer_pairs=1:halt_on_error=0 %run %t 2>&1 | FileCheck %s + +#include +#include + +int foo(char *p, char *q) { + return p > q; +} + +char global1[100] = {}, global2[100] = {}; +char small_global[7] = {}; +char large_global[5000] = {}; + +int main() { + // Heap allocated memory. + char *heap1 = (char *)malloc(42); + char *heap2 = (char *)malloc(42); + + // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair + // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-compare-errors.cc:[[@LINE+1]] + foo(heap1, heap2); + free(heap1); + free(heap2); + + heap1 = (char *)malloc(1024); + // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair + // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-compare-errors.cc:[[@LINE+1]] + foo(heap1, heap1 + 1025); + // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair + // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-compare-errors.cc:[[@LINE+1]] + foo(heap1 + 1024, heap1 + 1025); + free(heap1); + + heap1 = (char *)malloc(4096); + // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair + // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-compare-errors.cc:[[@LINE+1]] + foo(heap1, heap1 + 4097); + // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair + // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-compare-errors.cc:[[@LINE+1]] + foo(heap1, 0); + + // Global variables. + // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair + // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-compare-errors.cc:[[@LINE+1]] + foo(&global1[0], &global2[10]); + + char *p = &small_global[0]; + foo(p, p); // OK + foo(p, p + 7); // OK + // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair + // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-compare-errors.cc:[[@LINE+1]] + foo(p, p + 8); + // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair + // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-compare-errors.cc:[[@LINE+1]] + foo(p - 1, p); + // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair + // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-compare-errors.cc:[[@LINE+1]] + foo(p, p - 1); + // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair + // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-compare-errors.cc:[[@LINE+1]] + foo(p - 1, p + 8); + + p = &large_global[0]; + // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair + // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-compare-errors.cc:[[@LINE+1]] + foo(p - 1, p); + // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair + // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-compare-errors.cc:[[@LINE+1]] + foo(p, p - 1); + // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair + // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-compare-errors.cc:[[@LINE+1]] + foo(p, &global1[0]); + // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair + // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-compare-errors.cc:[[@LINE+1]] + foo(p, &small_global[0]); + // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair + // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-compare-errors.cc:[[@LINE+1]] + foo(p, 0); + + // Stack variables. + char stack1, stack2; + // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair + // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-compare-errors.cc:[[@LINE+1]] + foo(&stack1, &stack2); + + // Mixtures. + // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair + // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-compare-errors.cc:[[@LINE+1]] + foo(heap1, &stack1); + // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair + foo(heap1, &global1[0]); + // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair + foo(&stack1, &global1[0]); + // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair + // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-compare-errors.cc:[[@LINE+1]] + foo(&stack1, 0); + + free(heap1); + + return 0; +} diff --git a/test/asan/TestCases/invalid-pointer-pairs-compare-success.cc b/test/asan/TestCases/invalid-pointer-pairs-compare-success.cc new file mode 100644 index 000000000..565d39088 --- /dev/null +++ b/test/asan/TestCases/invalid-pointer-pairs-compare-success.cc @@ -0,0 +1,74 @@ +// RUN: %clangxx_asan -O0 %s -o %t -mllvm -asan-detect-invalid-pointer-pair + +// RUN: %env_asan_opts=detect_invalid_pointer_pairs=1 %run %t + +#include +#include + +int foo(char *p) { + char *p2 = p + 20; + return p > p2; +} + +int bar(char *p, char *q) { + return p <= q; +} + +int baz(char *p, char *q) { + return p != 0 && p < q; +} + +char global[8192] = {}; +char small_global[7] = {}; + +int main() { + // Heap allocated memory. + char *p = (char *)malloc(42); + int r = foo(p); + free(p); + + p = (char *)malloc(1024); + bar(p, p + 1024); + bar(p + 1024, p + 1023); + bar(p + 1, p + 1023); + free(p); + + p = (char *)malloc(4096); + bar(p, p + 4096); + bar(p + 10, p + 100); + bar(p + 1024, p + 4096); + bar(p + 4095, p + 4096); + bar(p + 4095, p + 4094); + bar(p + 100, p + 4096); + bar(p + 100, p + 4094); + free(p); + + // Global variable. + bar(&global[0], &global[1]); + bar(&global[1], &global[2]); + bar(&global[2], &global[1]); + bar(&global[0], &global[100]); + bar(&global[1000], &global[7000]); + bar(&global[500], &global[10]); + p = &global[0]; + bar(p, p + 8192); + p = &global[8000]; + bar(p, p + 192); + + p = &small_global[0]; + bar(p, p + 1); + bar(p, p + 7); + bar(p + 7, p + 1); + bar(p + 6, p + 7); + bar(p + 7, p + 7); + + // Stack variable. + char stack[10000]; + bar(&stack[0], &stack[100]); + bar(&stack[1000], &stack[9000]); + bar(&stack[500], &stack[10]); + + baz(0, &stack[10]); + + return 0; +} diff --git a/test/asan/TestCases/invalid-pointer-pairs-subtract-errors.cc b/test/asan/TestCases/invalid-pointer-pairs-subtract-errors.cc new file mode 100644 index 000000000..546f61f81 --- /dev/null +++ b/test/asan/TestCases/invalid-pointer-pairs-subtract-errors.cc @@ -0,0 +1,48 @@ +// RUN: %clangxx_asan -O0 %s -o %t -mllvm -asan-detect-invalid-pointer-pair + +// RUN: %env_asan_opts=detect_invalid_pointer_pairs=1:halt_on_error=0 %run %t 2>&1 | FileCheck %s + +#include +#include + +int foo(char *p, char *q) { + return p - q; +} + +char global1[100] = {}, global2[100] = {}; + +int main() { + // Heap allocated memory. + char *heap1 = (char *)malloc(42); + char *heap2 = (char *)malloc(42); + + // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair + // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-subtract-errors.cc:[[@LINE+1]] + foo(heap1, heap2); + + // Global variables. + // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair + // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-subtract-errors.cc:[[@LINE+1]] + foo(&global1[0], &global2[10]); + + // Stack variables. + char stack1, stack2; + // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair + // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-subtract-errors.cc:[[@LINE+1]] + foo(&stack1, &stack2); + + // Mixtures. + // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair + // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-subtract-errors.cc:[[@LINE+1]] + foo(heap1, &stack1); + // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair + // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-subtract-errors.cc:[[@LINE+1]] + foo(heap1, &global1[0]); + // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair + // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-subtract-errors.cc:[[@LINE+1]] + foo(&stack1, &global1[0]); + + free(heap1); + free(heap2); + return 0; +} diff --git a/test/asan/TestCases/invalid-pointer-pairs-subtract-success.cc b/test/asan/TestCases/invalid-pointer-pairs-subtract-success.cc new file mode 100644 index 000000000..4ce484248 --- /dev/null +++ b/test/asan/TestCases/invalid-pointer-pairs-subtract-success.cc @@ -0,0 +1,33 @@ +// RUN: %clangxx_asan -O0 %s -o %t -mllvm -asan-detect-invalid-pointer-pair + +// RUN: %env_asan_opts=detect_invalid_pointer_pairs=1 %run %t + +#include +#include + +int bar(char *p, char *q) { + return p <= q; +} + +char global[10000] = {}; + +int main() { + // Heap allocated memory. + char *p = (char *)malloc(42); + int r = bar(p, p + 20); + free(p); + + // Global variable. + bar(&global[0], &global[100]); + bar(&global[1000], &global[9000]); + bar(&global[500], &global[10]); + bar(&global[0], &global[10000]); + + // Stack variable. + char stack[10000]; + bar(&stack[0], &stack[100]); + bar(&stack[1000], &stack[9000]); + bar(&stack[500], &stack[10]); + + return 0; +} -- cgit v1.2.3