[compiler-rt] r201664 - [asan] Improve stack overflow detection.

Evgeniy Stepanov eugeni.stepanov at gmail.com
Wed Feb 19 03:02:46 PST 2014


Author: eugenis
Date: Wed Feb 19 05:02:46 2014
New Revision: 201664

URL: http://llvm.org/viewvc/llvm-project?rev=201664&view=rev
Log:
[asan] Improve stack overflow detection.

There are more cases when those manifest as an access below SP.

Modified:
    compiler-rt/trunk/lib/asan/asan_report.cc
    compiler-rt/trunk/test/asan/TestCases/stack-overflow.cc

Modified: compiler-rt/trunk/lib/asan/asan_report.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_report.cc?rev=201664&r1=201663&r2=201664&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_report.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_report.cc Wed Feb 19 05:02:46 2014
@@ -570,14 +570,12 @@ class ScopedInErrorReport {
 
 static bool IsStackOverflow(uptr addr, uptr sp) {
   uptr stack_frame_bottom = sp;
-#ifdef __x86_64__
-  stack_frame_bottom -= 128; // x86_64 stack redzone
-#else
-  // call stores return value 1 word below SP.
-  stack_frame_bottom -= sizeof(uptr);
-#endif
-  // Access below sp (+ redzone on x86_64) is probably something else (like
-  // stack of another thread).
+  // x86_64 stack redzone: leaf functions can access up to 128 bytes below SP.
+  // ARM has push-multiple instruction that stores up to 64(?) bytes below SP.
+  stack_frame_bottom -= 128;
+
+  // Access below SP (minus redzone) is probably something else (like stack of
+  // another thread).
   if (addr < stack_frame_bottom)
     return false;
 

Modified: compiler-rt/trunk/test/asan/TestCases/stack-overflow.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/stack-overflow.cc?rev=201664&r1=201663&r2=201664&view=diff
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/stack-overflow.cc (original)
+++ compiler-rt/trunk/test/asan/TestCases/stack-overflow.cc Wed Feb 19 05:02:46 2014
@@ -1,6 +1,17 @@
+// Test ASan detection of stack-overflow condition.
+
+// RUN: %clangxx_asan -O0 %s -DSMALL_FRAME -o %t && ASAN_OPTIONS=use_sigaltstack=1 not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -DSMALL_FRAME -o %t && ASAN_OPTIONS=use_sigaltstack=1 not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O0 %s -DSAVE_ALL_THE_REGISTERS -o %t && ASAN_OPTIONS=use_sigaltstack=1 not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -DSAVE_ALL_THE_REGISTERS -o %t && ASAN_OPTIONS=use_sigaltstack=1 not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O0 %s -o %t && ASAN_OPTIONS=use_sigaltstack=1 not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -o %t && ASAN_OPTIONS=use_sigaltstack=1 not %t 2>&1 | FileCheck %s
+
+// RUN: %clangxx_asan -O0 %s -DTHREAD -DSMALL_FRAME -o %t && ASAN_OPTIONS=use_sigaltstack=1 not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -DTHREAD -DSMALL_FRAME -o %t && ASAN_OPTIONS=use_sigaltstack=1 not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O0 %s -DTHREAD -DSAVE_ALL_THE_REGISTERS -o %t && ASAN_OPTIONS=use_sigaltstack=1 not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -DTHREAD -DSAVE_ALL_THE_REGISTERS -o %t && ASAN_OPTIONS=use_sigaltstack=1 not %t 2>&1 | FileCheck %s
 // RUN: %clangxx_asan -O0 %s -DTHREAD -o %t && ASAN_OPTIONS=use_sigaltstack=1 not %t 2>&1 | FileCheck %s
-// RUN: %clangxx_asan -O1 %s -DTHREAD -o %t && ASAN_OPTIONS=use_sigaltstack=1 not %t 2>&1 | FileCheck %s
-// RUN: %clangxx_asan -O2 %s -DTHREAD -o %t && ASAN_OPTIONS=use_sigaltstack=1 not %t 2>&1 | FileCheck %s
 // RUN: %clangxx_asan -O3 %s -DTHREAD -o %t && ASAN_OPTIONS=use_sigaltstack=1 not %t 2>&1 | FileCheck %s
 
 #include <assert.h>
@@ -9,24 +20,63 @@
 
 const int BS = 1024;
 volatile char x;
+volatile int y = 1;
+volatile int z0, z1, z2, z3, z4, z5, z6, z7, z8, z9, z10, z11, z12, z13;
+
+void recursive_func(char *p) {
+#if defined(SMALL_FRAME)
+  char *buf = 0;
+#elif defined(SAVE_ALL_THE_REGISTERS)
+  char *buf = 0;
+  int t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13;
+  t0 = z0;
+  t1 = z1;
+  t2 = z2;
+  t3 = z3;
+  t4 = z4;
+  t5 = z5;
+  t6 = z6;
+  t7 = z7;
+  t8 = z8;
+  t9 = z9;
+  t10 = z10;
+  t11 = z11;
+  t12 = z12;
+  t13 = z13;
 
-void large_frame_func(char *p, int level) {
+  z0 = t0;
+  z1 = t1;
+  z2 = t2;
+  z3 = t3;
+  z4 = t4;
+  z5 = t5;
+  z6 = t6;
+  z7 = t7;
+  z8 = t8;
+  z9 = t9;
+  z10 = t10;
+  z11 = t11;
+  z12 = t12;
+  z13 = t13;
+#else
   char buf[BS];
   if (p)
     assert(p - buf >= BS);
   buf[rand() % BS] = 1;
   buf[rand() % BS] = 2;
   x = buf[rand() % BS];
-  volatile int y = 1;
+#endif
   if (y)
-    large_frame_func(buf, level + 1);
+    recursive_func(buf);
+  x = 1; // prevent tail call optimization
   // CHECK: {{stack-overflow on address 0x.* \(pc 0x.* sp 0x.* bp 0x.* T.*\)}}
-  // Frame 0 may be anywhere (in rand(), for example).
-  // CHECK: {{    #. 0x.* in large_frame_func.*stack-overflow.cc:}}[[@LINE-3]]
+  // If stack overflow happens during function prologue, stack trace may be
+  // corrupted. Unwind tables are not always 100% exact there.
+  // For this reason, we don't do any further checks.
 }
 
 void *ThreadFn(void* unused) {
-  large_frame_func(0, 0);
+  recursive_func(0);
   return 0;
 }
 
@@ -36,7 +86,7 @@ int main(int argc, char **argv) {
   pthread_create(&t, 0, ThreadFn, 0);
   pthread_join(t, 0);
 #else
-  large_frame_func(0, 0);
+  recursive_func(0);
 #endif
   return 0;
 }





More information about the llvm-commits mailing list