[asan] workaround for asan bug 189 (swapcontext followed by throw gets OOM kill). Also, disable swapcontext_test on non-x86. Fix lint

llvm-svn: 182456
This commit is contained in:
Kostya Serebryany 2013-05-22 08:54:30 +00:00
parent 13c37b3483
commit 8410a867eb
4 changed files with 55 additions and 10 deletions

View File

@ -423,6 +423,20 @@ void NOINLINE __asan_handle_no_return() {
uptr PageSize = GetPageSizeCached();
uptr top = curr_thread->stack_top();
uptr bottom = ((uptr)&local_stack - PageSize) & ~(PageSize-1);
static const uptr kMaxExpectedCleanupSize = 64 << 20; // 64M
if (top - bottom > kMaxExpectedCleanupSize) {
static bool reported_warning = false;
if (reported_warning)
return;
reported_warning = true;
Report("WARNING: ASan is ignoring requested __asan_handle_no_return: "
"stack top: %p; bottom %p; size: %p (%zd)\n"
"False positive error reports may follow\n"
"For details see "
"http://code.google.com/p/address-sanitizer/issues/detail?id=189\n",
top, bottom, top - bottom, top - bottom);
return;
}
PoisonShadow(bottom, top - bottom, 0);
}

View File

@ -8,6 +8,9 @@
// RUN: %clangxx_asan -m32 -O1 %s -o %t && %t 2>&1 | FileCheck %s
// RUN: %clangxx_asan -m32 -O2 %s -o %t && %t 2>&1 | FileCheck %s
// RUN: %clangxx_asan -m32 -O3 %s -o %t && %t 2>&1 | FileCheck %s
//
// This test is too sublte to try on non-x86 arch for now.
// REQUIRES: x86_64-supported-target,i386-supported-target
#include <stdio.h>
#include <ucontext.h>
@ -16,9 +19,26 @@
ucontext_t orig_context;
ucontext_t child_context;
const int kStackSize = 1 << 20;
__attribute__((noinline))
void Throw() {
throw 1;
}
__attribute__((noinline))
void ThrowAndCatch() {
try {
Throw();
} catch(int a) {
printf("ThrowAndCatch: %d\n", a);
}
}
void Child(int mode) {
char x[32] = {0}; // Stack gets poisoned.
printf("Child: %p\n", x);
ThrowAndCatch(); // Simulate __asan_handle_no_return().
// (a) Do nothing, just return to parent function.
// (b) Jump into the original function. Stack remains poisoned unless we do
// something.
@ -30,9 +50,7 @@ void Child(int mode) {
}
}
int Run(int arg, int mode) {
const int kStackSize = 1 << 20;
char child_stack[kStackSize + 1];
int Run(int arg, int mode, char *child_stack) {
printf("Child stack: %p\n", child_stack);
// Setup child context.
getcontext(&child_context);
@ -54,13 +72,23 @@ int Run(int arg, int mode) {
}
int main(int argc, char **argv) {
char stack[kStackSize + 1];
// CHECK: WARNING: ASan doesn't fully support makecontext/swapcontext
int ret = 0;
ret += Run(argc - 1, 0);
ret += Run(argc - 1, 0, stack);
printf("Test1 passed\n");
// CHECK: Test1 passed
ret += Run(argc - 1, 1);
ret += Run(argc - 1, 1, stack);
printf("Test2 passed\n");
// CHECK: Test2 passed
char *heap = new char[kStackSize + 1];
ret += Run(argc - 1, 0, heap);
printf("Test3 passed\n");
// CHECK: Test3 passed
ret += Run(argc - 1, 1, heap);
printf("Test4 passed\n");
// CHECK: Test4 passed
delete [] heap;
return ret;
}

View File

@ -1221,10 +1221,12 @@ TEST(AddressSanitizer, LongDoubleNegativeTest) {
TEST(AddressSanitizer, pthread_getschedparam) {
int policy;
struct sched_param param;
EXPECT_DEATH(pthread_getschedparam(pthread_self(), &policy, Ident(&param) + 2),
"AddressSanitizer: stack-buffer-overflow");
EXPECT_DEATH(pthread_getschedparam(pthread_self(), Ident(&policy) - 1, &param),
"AddressSanitizer: stack-buffer-overflow");
EXPECT_DEATH(
pthread_getschedparam(pthread_self(), &policy, Ident(&param) + 2),
"AddressSanitizer: stack-buffer-overflow");
EXPECT_DEATH(
pthread_getschedparam(pthread_self(), Ident(&policy) - 1, &param),
"AddressSanitizer: stack-buffer-overflow");
int res = pthread_getschedparam(pthread_self(), &policy, &param);
ASSERT_EQ(0, res);
}

View File

@ -651,7 +651,8 @@ INTERCEPTOR_WITH_SUFFIX(int, wait, int *status) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
return res;
}
INTERCEPTOR_WITH_SUFFIX(int, waitid, int idtype, int id, void *infop, int options) {
INTERCEPTOR_WITH_SUFFIX(int, waitid, int idtype, int id, void *infop,
int options) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, waitid, idtype, id, infop, options);
int res = REAL(waitid)(idtype, id, infop, options);