diff options
| author | Kostya Serebryany <kcc@google.com> | 2013-04-10 13:59:32 +0000 |
|---|---|---|
| committer | Kostya Serebryany <kcc@google.com> | 2013-04-10 13:59:32 +0000 |
| commit | 92684efb1daa651d8f0b47180ce51a587929b3c3 (patch) | |
| tree | 1121cdc7bd8942f55b4ed73a8ac506500ebf31bf | |
| parent | 04d9aa48226393f3c29e1060e1950ee09c018e65 (diff) | |
| download | bcm5719-llvm-92684efb1daa651d8f0b47180ce51a587929b3c3.tar.gz bcm5719-llvm-92684efb1daa651d8f0b47180ce51a587929b3c3.zip | |
[asan] implement callbacks for unaligned loads/stores
Reviewers: samsonov
Reviewed By: samsonov
CC: samsonov, llvm-commits
Differential Revision: http://llvm-reviews.chandlerc.com/D652
llvm-svn: 179175
| -rw-r--r-- | compiler-rt/include/sanitizer/common_interface_defs.h | 10 | ||||
| -rw-r--r-- | compiler-rt/lib/asan/asan_poisoning.cc | 49 | ||||
| -rw-r--r-- | compiler-rt/lib/asan/lit_tests/unaligned_loads_and_stores.cc | 52 |
3 files changed, 111 insertions, 0 deletions
diff --git a/compiler-rt/include/sanitizer/common_interface_defs.h b/compiler-rt/include/sanitizer/common_interface_defs.h index 74e3b22ccf9..31d0dea5484 100644 --- a/compiler-rt/include/sanitizer/common_interface_defs.h +++ b/compiler-rt/include/sanitizer/common_interface_defs.h @@ -41,6 +41,16 @@ extern "C" { // the error message. This function can be overridden by the client. void __sanitizer_report_error_summary(const char *error_summary); + // Some of the sanitizers (e.g. asan/tsan) may miss bugs that happen + // in unaligned loads/stores. In order to find such bugs reliably one needs + // to replace plain unaligned loads/stores with these calls. + uint16_t __sanitizer_unaligned_load16(const void *p); + uint32_t __sanitizer_unaligned_load32(const void *p); + uint64_t __sanitizer_unaligned_load64(const void *p); + void __sanitizer_unaligned_store16(void *p, uint16_t x); + void __sanitizer_unaligned_store32(void *p, uint32_t x); + void __sanitizer_unaligned_store64(void *p, uint64_t x); + #ifdef __cplusplus } // extern "C" #endif diff --git a/compiler-rt/lib/asan/asan_poisoning.cc b/compiler-rt/lib/asan/asan_poisoning.cc index e8b08d2057f..772b5e64b02 100644 --- a/compiler-rt/lib/asan/asan_poisoning.cc +++ b/compiler-rt/lib/asan/asan_poisoning.cc @@ -169,6 +169,55 @@ uptr __asan_region_is_poisoned(uptr beg, uptr size) { return 0; } +#define CHECK_SMALL_REGION(p, size, isWrite) \ + do { \ + uptr __p = reinterpret_cast<uptr>(p); \ + uptr __size = size; \ + if (UNLIKELY(__asan::AddressIsPoisoned(__p) || \ + __asan::AddressIsPoisoned(__p + __size - 1))) { \ + GET_CURRENT_PC_BP_SP; \ + uptr __bad = __asan_region_is_poisoned(__p, __size); \ + __asan_report_error(pc, bp, sp, __bad, isWrite, __size);\ + } \ + } while (false); \ + + +extern "C" SANITIZER_INTERFACE_ATTRIBUTE +u16 __sanitizer_unaligned_load16(const u16 *p) { + CHECK_SMALL_REGION(p, sizeof(*p), false); + return *p; +} + +extern "C" SANITIZER_INTERFACE_ATTRIBUTE +u32 __sanitizer_unaligned_load32(const u32 *p) { + CHECK_SMALL_REGION(p, sizeof(*p), false); + return *p; +} + +extern "C" SANITIZER_INTERFACE_ATTRIBUTE +u64 __sanitizer_unaligned_load64(const u64 *p) { + CHECK_SMALL_REGION(p, sizeof(*p), false); + return *p; +} + +extern "C" SANITIZER_INTERFACE_ATTRIBUTE +void __sanitizer_unaligned_store16(u16 *p, u16 x) { + CHECK_SMALL_REGION(p, sizeof(*p), true); + *p = x; +} + +extern "C" SANITIZER_INTERFACE_ATTRIBUTE +void __sanitizer_unaligned_store32(u32 *p, u32 x) { + CHECK_SMALL_REGION(p, sizeof(*p), true); + *p = x; +} + +extern "C" SANITIZER_INTERFACE_ATTRIBUTE +void __sanitizer_unaligned_store64(u64 *p, u64 x) { + CHECK_SMALL_REGION(p, sizeof(*p), true); + *p = x; +} + // This is a simplified version of __asan_(un)poison_memory_region, which // assumes that left border of region to be poisoned is properly aligned. static void PoisonAlignedStackMemory(uptr addr, uptr size, bool do_poison) { diff --git a/compiler-rt/lib/asan/lit_tests/unaligned_loads_and_stores.cc b/compiler-rt/lib/asan/lit_tests/unaligned_loads_and_stores.cc new file mode 100644 index 00000000000..bcae089b427 --- /dev/null +++ b/compiler-rt/lib/asan/lit_tests/unaligned_loads_and_stores.cc @@ -0,0 +1,52 @@ +// RUN: %clangxx_asan -O0 -I %p/../../../include %s -o %t +// RUN: %t A 2>&1 | %symbolize | FileCheck --check-prefix=CHECK-A %s +// RUN: %t B 2>&1 | %symbolize | FileCheck --check-prefix=CHECK-B %s +// RUN: %t C 2>&1 | %symbolize | FileCheck --check-prefix=CHECK-C %s +// RUN: %t D 2>&1 | %symbolize | FileCheck --check-prefix=CHECK-D %s +// RUN: %t E 2>&1 | %symbolize | FileCheck --check-prefix=CHECK-E %s + +// RUN: %t K 2>&1 | %symbolize | FileCheck --check-prefix=CHECK-K %s +// RUN: %t L 2>&1 | %symbolize | FileCheck --check-prefix=CHECK-L %s +// RUN: %t M 2>&1 | %symbolize | FileCheck --check-prefix=CHECK-M %s +// RUN: %t N 2>&1 | %symbolize | FileCheck --check-prefix=CHECK-N %s +// RUN: %t O 2>&1 | %symbolize | FileCheck --check-prefix=CHECK-O %s + +#include <sanitizer/asan_interface.h> + +#include <stdlib.h> +#include <string.h> +int main(int argc, char **argv) { + if (argc != 2) return 1; + char *x = new char[16]; + memset(x, 0xab, 16); + int res = 1; + switch (argv[1][0]) { + case 'A': res = __sanitizer_unaligned_load16(x + 15); break; +// CHECK-A ERROR: AddressSanitizer: heap-buffer-overflow on address +// CHECK-A: main{{.*}}unaligned_loads_and_stores.cc:[[@LINE-2]] +// CHECK-A: is located 0 bytes to the right of 16-byte region + case 'B': res = __sanitizer_unaligned_load32(x + 14); break; +// CHECK-B: main{{.*}}unaligned_loads_and_stores.cc:[[@LINE-1]] + case 'C': res = __sanitizer_unaligned_load32(x + 13); break; +// CHECK-C: main{{.*}}unaligned_loads_and_stores.cc:[[@LINE-1]] + case 'D': res = __sanitizer_unaligned_load64(x + 15); break; +// CHECK-D: main{{.*}}unaligned_loads_and_stores.cc:[[@LINE-1]] + case 'E': res = __sanitizer_unaligned_load64(x + 9); break; +// CHECK-E: main{{.*}}unaligned_loads_and_stores.cc:[[@LINE-1]] + + case 'K': __sanitizer_unaligned_store16(x + 15, 0); break; +// CHECK-K ERROR: AddressSanitizer: heap-buffer-overflow on address +// CHECK-K: main{{.*}}unaligned_loads_and_stores.cc:[[@LINE-2]] +// CHECK-K: is located 0 bytes to the right of 16-byte region + case 'L': __sanitizer_unaligned_store32(x + 15, 0); break; +// CHECK-L: main{{.*}}unaligned_loads_and_stores.cc:[[@LINE-1]] + case 'M': __sanitizer_unaligned_store32(x + 13, 0); break; +// CHECK-M: main{{.*}}unaligned_loads_and_stores.cc:[[@LINE-1]] + case 'N': __sanitizer_unaligned_store64(x + 10, 0); break; +// CHECK-N: main{{.*}}unaligned_loads_and_stores.cc:[[@LINE-1]] + case 'O': __sanitizer_unaligned_store64(x + 14, 0); break; +// CHECK-O: main{{.*}}unaligned_loads_and_stores.cc:[[@LINE-1]] + } + delete x; + return res; +} |

