From 30a990744b777c4d8414df452e5800cd1d67f352 Mon Sep 17 00:00:00 2001 From: Yury Gribov Date: Fri, 21 Nov 2014 10:32:05 +0000 Subject: [PATCH] [asan] Runtime support for asan-instrument-allocas which enables instrumentation of variable-sized dynamic allocas. Patch by Max Ostapenko. Reviewed at http://reviews.llvm.org/D6055 llvm-svn: 222520 --- compiler-rt/lib/asan/asan_internal.h | 2 ++ compiler-rt/lib/asan/asan_report.cc | 8 ++++++++ .../test/asan/TestCases/alloca_big_alignment.cc | 18 +++++++++++++++++ .../asan/TestCases/alloca_detect_custom_size_.cc | 23 ++++++++++++++++++++++ .../TestCases/alloca_instruments_all_paddings.cc | 23 ++++++++++++++++++++++ .../test/asan/TestCases/alloca_overflow_partial.cc | 18 +++++++++++++++++ .../test/asan/TestCases/alloca_overflow_right.cc | 18 +++++++++++++++++ .../test/asan/TestCases/alloca_safe_access.cc | 17 ++++++++++++++++ .../test/asan/TestCases/alloca_underflow_left.cc | 18 +++++++++++++++++ 9 files changed, 145 insertions(+) create mode 100644 compiler-rt/test/asan/TestCases/alloca_big_alignment.cc create mode 100644 compiler-rt/test/asan/TestCases/alloca_detect_custom_size_.cc create mode 100644 compiler-rt/test/asan/TestCases/alloca_instruments_all_paddings.cc create mode 100644 compiler-rt/test/asan/TestCases/alloca_overflow_partial.cc create mode 100644 compiler-rt/test/asan/TestCases/alloca_overflow_right.cc create mode 100644 compiler-rt/test/asan/TestCases/alloca_safe_access.cc create mode 100644 compiler-rt/test/asan/TestCases/alloca_underflow_left.cc diff --git a/compiler-rt/lib/asan/asan_internal.h b/compiler-rt/lib/asan/asan_internal.h index f9f9243..3771a01 100644 --- a/compiler-rt/lib/asan/asan_internal.h +++ b/compiler-rt/lib/asan/asan_internal.h @@ -136,6 +136,8 @@ const int kAsanGlobalRedzoneMagic = 0xf9; const int kAsanInternalHeapMagic = 0xfe; const int kAsanArrayCookieMagic = 0xac; const int kAsanIntraObjectRedzone = 0xbb; +const int kAsanAllocaLeftMagic = 0xca; +const int kAsanAllocaRightMagic = 0xcb; static const uptr kCurrentStackFrameMagic = 0x41B58AB3; static const uptr kRetiredStackFrameMagic = 0x45E0360E; diff --git a/compiler-rt/lib/asan/asan_report.cc b/compiler-rt/lib/asan/asan_report.cc index 2ca11a3..7b56c9b 100644 --- a/compiler-rt/lib/asan/asan_report.cc +++ b/compiler-rt/lib/asan/asan_report.cc @@ -87,6 +87,8 @@ class Decorator: public __sanitizer::SanitizerCommonDecorator { return Cyan(); case kAsanUserPoisonedMemoryMagic: case kAsanContiguousContainerOOBMagic: + case kAsanAllocaLeftMagic: + case kAsanAllocaRightMagic: return Blue(); case kAsanStackUseAfterScopeMagic: return Magenta(); @@ -173,6 +175,8 @@ static void PrintLegend(InternalScopedString *str) { PrintShadowByte(str, " Intra object redzone: ", kAsanIntraObjectRedzone); PrintShadowByte(str, " ASan internal: ", kAsanInternalHeapMagic); + PrintShadowByte(str, " Left alloca redzone: ", kAsanAllocaLeftMagic); + PrintShadowByte(str, " Right alloca redzone: ", kAsanAllocaRightMagic); } void MaybeDumpInstructionBytes(uptr pc) { @@ -982,6 +986,10 @@ void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write, case kAsanIntraObjectRedzone: bug_descr = "intra-object-overflow"; break; + case kAsanAllocaLeftMagic: + case kAsanAllocaRightMagic: + bug_descr = "dynamic-stack-buffer-overflow"; + break; } } diff --git a/compiler-rt/test/asan/TestCases/alloca_big_alignment.cc b/compiler-rt/test/asan/TestCases/alloca_big_alignment.cc new file mode 100644 index 0000000..2ede3f9 --- /dev/null +++ b/compiler-rt/test/asan/TestCases/alloca_big_alignment.cc @@ -0,0 +1,18 @@ +// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-allocas %s -o %t +// RUN: not %run %t 2>&1 | FileCheck %s +// + +#include + +__attribute__((noinline)) void foo(int index, int len) { + volatile char str[len] __attribute__((aligned(128))); + assert(!(reinterpret_cast(str) & 127L)); + str[index] = '1'; // BOOM +// CHECK: ERROR: AddressSanitizer: dynamic-stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] +// CHECK: WRITE of size 1 at [[ADDR]] thread T0 +} + +int main(int argc, char **argv) { + foo(10, 10); + return 0; +} diff --git a/compiler-rt/test/asan/TestCases/alloca_detect_custom_size_.cc b/compiler-rt/test/asan/TestCases/alloca_detect_custom_size_.cc new file mode 100644 index 0000000..2b0f573 --- /dev/null +++ b/compiler-rt/test/asan/TestCases/alloca_detect_custom_size_.cc @@ -0,0 +1,23 @@ +// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-allocas %s -o %t +// RUN: not %run %t 2>&1 | FileCheck %s +// + +#include + +struct A { + char a[3]; + int b[3]; +}; + +__attribute__((noinline)) void foo(int index, int len) { + volatile struct A str[len] __attribute__((aligned(32))); + assert(!(reinterpret_cast(str) & 31L)); + str[index].a[0] = '1'; // BOOM +// CHECK: ERROR: AddressSanitizer: dynamic-stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] +// CHECK: WRITE of size 1 at [[ADDR]] thread T0 +} + +int main(int argc, char **argv) { + foo(10, 10); + return 0; +} diff --git a/compiler-rt/test/asan/TestCases/alloca_instruments_all_paddings.cc b/compiler-rt/test/asan/TestCases/alloca_instruments_all_paddings.cc new file mode 100644 index 0000000..d60a3b2 --- /dev/null +++ b/compiler-rt/test/asan/TestCases/alloca_instruments_all_paddings.cc @@ -0,0 +1,23 @@ +// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-allocas %s -o %t +// RUN: %run %t 2>&1 +// + +#include "sanitizer/asan_interface.h" +#include + +__attribute__((noinline)) void foo(int index, int len) { + volatile char str[len] __attribute__((aligned(32))); + assert(!(reinterpret_cast(str) & 31L)); + char *q = (char *)__asan_region_is_poisoned((char *)str, 64); + assert(q && ((q - str) == index)); +} + +int main(int argc, char **argv) { + for (int i = 1; i < 33; ++i) + foo(i, i); + + for (int i = 1; i < 33; ++i) + foo(i, i); + + return 0; +} diff --git a/compiler-rt/test/asan/TestCases/alloca_overflow_partial.cc b/compiler-rt/test/asan/TestCases/alloca_overflow_partial.cc new file mode 100644 index 0000000..590f354 --- /dev/null +++ b/compiler-rt/test/asan/TestCases/alloca_overflow_partial.cc @@ -0,0 +1,18 @@ +// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-allocas %s -o %t +// RUN: not %run %t 2>&1 | FileCheck %s +// + +#include + +__attribute__((noinline)) void foo(int index, int len) { + volatile char str[len] __attribute__((aligned(32))); + assert(!(reinterpret_cast(str) & 31L)); + str[index] = '1'; // BOOM +// CHECK: ERROR: AddressSanitizer: dynamic-stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] +// CHECK: WRITE of size 1 at [[ADDR]] thread T0 +} + +int main(int argc, char **argv) { + foo(10, 10); + return 0; +} diff --git a/compiler-rt/test/asan/TestCases/alloca_overflow_right.cc b/compiler-rt/test/asan/TestCases/alloca_overflow_right.cc new file mode 100644 index 0000000..caec846 --- /dev/null +++ b/compiler-rt/test/asan/TestCases/alloca_overflow_right.cc @@ -0,0 +1,18 @@ +// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-allocas %s -o %t +// RUN: not %run %t 2>&1 | FileCheck %s +// + +#include + +__attribute__((noinline)) void foo(int index, int len) { + volatile char str[len] __attribute__((aligned(32))); + assert(!(reinterpret_cast(str) & 31L)); + str[index] = '1'; // BOOM +// CHECK: ERROR: AddressSanitizer: dynamic-stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] +// CHECK: WRITE of size 1 at [[ADDR]] thread T0 +} + +int main(int argc, char **argv) { + foo(33, 10); + return 0; +} diff --git a/compiler-rt/test/asan/TestCases/alloca_safe_access.cc b/compiler-rt/test/asan/TestCases/alloca_safe_access.cc new file mode 100644 index 0000000..240454f --- /dev/null +++ b/compiler-rt/test/asan/TestCases/alloca_safe_access.cc @@ -0,0 +1,17 @@ +// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-allocas %s -o %t +// RUN: %run %t 2>&1 +// + +#include + +__attribute__((noinline)) void foo(int index, int len) { + volatile char str[len] __attribute__((aligned(32))); + assert(!(reinterpret_cast(str) & 31L)); + str[index] = '1'; +} + +int main(int argc, char **argv) { + foo(4, 5); + foo(39, 40); + return 0; +} diff --git a/compiler-rt/test/asan/TestCases/alloca_underflow_left.cc b/compiler-rt/test/asan/TestCases/alloca_underflow_left.cc new file mode 100644 index 0000000..6e7061f --- /dev/null +++ b/compiler-rt/test/asan/TestCases/alloca_underflow_left.cc @@ -0,0 +1,18 @@ +// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-allocas %s -o %t +// RUN: not %run %t 2>&1 | FileCheck %s +// + +#include + +__attribute__((noinline)) void foo(int index, int len) { + volatile char str[len] __attribute__((aligned(32))); + assert(!(reinterpret_cast(str) & 31L)); + str[index] = '1'; // BOOM +// CHECK: ERROR: AddressSanitizer: dynamic-stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] +// CHECK: WRITE of size 1 at [[ADDR]] thread T0 +} + +int main(int argc, char **argv) { + foo(-1, 10); + return 0; +} -- 2.7.4