diff --git a/compiler-rt/lib/asan/asan_interceptors.cpp b/compiler-rt/lib/asan/asan_interceptors.cpp --- a/compiler-rt/lib/asan/asan_interceptors.cpp +++ b/compiler-rt/lib/asan/asan_interceptors.cpp @@ -248,8 +248,7 @@ uptr bottom = stack & ~(PageSize - 1); ssize += stack - bottom; ssize = RoundUpTo(ssize, PageSize); - static const uptr kMaxSaneContextStackSize = 1 << 22; // 4 Mb - if (AddrIsInMem(bottom) && ssize && ssize <= kMaxSaneContextStackSize) + if (AddrIsInMem(bottom) && ssize) PoisonShadow(bottom, ssize, 0); } diff --git a/compiler-rt/test/asan/TestCases/Linux/swapcontext_annotation.cpp b/compiler-rt/test/asan/TestCases/Linux/swapcontext_annotation.cpp --- a/compiler-rt/test/asan/TestCases/Linux/swapcontext_annotation.cpp +++ b/compiler-rt/test/asan/TestCases/Linux/swapcontext_annotation.cpp @@ -146,9 +146,61 @@ return child_stack[arg]; } +ucontext_t orig_huge_stack_context; +ucontext_t child_huge_stack_context; + +// There used to be a limitation for stack unpoisoning (size <= 4Mb), check that it's gone. +const int kHugeStackSize = 1 << 23; + +void ChildHugeStack() { + __sanitizer_finish_switch_fiber(nullptr, &main_thread_stack, + &main_thread_stacksize); + char x[32] = {0}; // Stack gets poisoned. + __sanitizer_start_switch_fiber(nullptr, main_thread_stack, + main_thread_stacksize); + if (swapcontext(&child_huge_stack_context, &orig_huge_stack_context) < 0) { + perror("swapcontext"); + _exit(1); + } +} + +void DoRunHugeStack(char *child_stack) { + getcontext(&child_huge_stack_context); + child_huge_stack_context.uc_stack.ss_sp = child_stack; + child_huge_stack_context.uc_stack.ss_size = kHugeStackSize; + makecontext(&child_huge_stack_context, (void (*)())ChildHugeStack, 0); + void *fake_stack_save; + __sanitizer_start_switch_fiber(&fake_stack_save, + child_huge_stack_context.uc_stack.ss_sp, + child_huge_stack_context.uc_stack.ss_size); + if (swapcontext(&orig_huge_stack_context, &child_huge_stack_context) < 0) { + perror("swapcontext"); + _exit(1); + } + __sanitizer_finish_switch_fiber( + fake_stack_save, (const void **)&child_huge_stack_context.uc_stack.ss_sp, + &child_huge_stack_context.uc_stack.ss_size); + for (int i = 0; i < kHugeStackSize; ++i) { + child_stack[i] = i; + } +} + +void RunHugeStack() { + const int run_offset = 1 << 14; + char *heap = new char[kHugeStackSize + run_offset + 1]; + DoRunHugeStack(heap); + DoRunHugeStack(heap + run_offset); + DoRunHugeStack(heap); + delete[] heap; +} + void handler(int sig) { CallNoReturn(); } int main(int argc, char **argv) { + // CHECK: WARNING: ASan doesn't fully support makecontext/swapcontext + // CHECK-NOT: ASan is ignoring requested __asan_handle_no_return + RunHugeStack(); + // set up a signal that will spam and trigger __asan_handle_no_return at // tricky moments struct sigaction act = {}; @@ -170,7 +222,6 @@ char *heap = new char[kStackSize + 1]; next_child_stack = new char[kStackSize + 1]; char stack[kStackSize + 1]; - // CHECK: WARNING: ASan doesn't fully support makecontext/swapcontext int ret = 0; // CHECK-NOT: ASan is ignoring requested __asan_handle_no_return for (unsigned int i = 0; i < 30; ++i) {