forked from OSchip/llvm-project
				
			[asan] fix one more case where stack-use-after-return is not async-signal-safe (during thread startup). beef-up the test to give it a chance to catch regressions. Also relax the lint to make C++11 more usable.
llvm-svn: 304598
This commit is contained in:
		
							parent
							
								
									6aeacaa527
								
							
						
					
					
						commit
						ad272b0861
					
				| 
						 | 
					@ -166,16 +166,19 @@ void AsanThread::FinishSwitchFiber(FakeStack *fake_stack_save,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
inline AsanThread::StackBounds AsanThread::GetStackBounds() const {
 | 
					inline AsanThread::StackBounds AsanThread::GetStackBounds() const {
 | 
				
			||||||
  if (!atomic_load(&stack_switching_, memory_order_acquire))
 | 
					  if (!atomic_load(&stack_switching_, memory_order_acquire)) {
 | 
				
			||||||
    return StackBounds{stack_bottom_, stack_top_};  // NOLINT
 | 
					    // Make sure the stack bounds are fully initialized.
 | 
				
			||||||
 | 
					    if (stack_bottom_ >= stack_top_) return {0, 0};
 | 
				
			||||||
 | 
					    return {stack_bottom_, stack_top_};
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
  char local;
 | 
					  char local;
 | 
				
			||||||
  const uptr cur_stack = (uptr)&local;
 | 
					  const uptr cur_stack = (uptr)&local;
 | 
				
			||||||
  // Note: need to check next stack first, because FinishSwitchFiber
 | 
					  // Note: need to check next stack first, because FinishSwitchFiber
 | 
				
			||||||
  // may be in process of overwriting stack_top_/bottom_. But in such case
 | 
					  // may be in process of overwriting stack_top_/bottom_. But in such case
 | 
				
			||||||
  // we are already on the next stack.
 | 
					  // we are already on the next stack.
 | 
				
			||||||
  if (cur_stack >= next_stack_bottom_ && cur_stack < next_stack_top_)
 | 
					  if (cur_stack >= next_stack_bottom_ && cur_stack < next_stack_top_)
 | 
				
			||||||
    return StackBounds{next_stack_bottom_, next_stack_top_};  // NOLINT
 | 
					    return {next_stack_bottom_, next_stack_top_};
 | 
				
			||||||
  return StackBounds{stack_bottom_, stack_top_};              // NOLINT
 | 
					  return {stack_bottom_, stack_top_};
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
uptr AsanThread::stack_top() {
 | 
					uptr AsanThread::stack_top() {
 | 
				
			||||||
| 
						 | 
					@ -197,6 +200,7 @@ FakeStack *AsanThread::AsyncSignalSafeLazyInitFakeStack() {
 | 
				
			||||||
  uptr stack_size = this->stack_size();
 | 
					  uptr stack_size = this->stack_size();
 | 
				
			||||||
  if (stack_size == 0)  // stack_size is not yet available, don't use FakeStack.
 | 
					  if (stack_size == 0)  // stack_size is not yet available, don't use FakeStack.
 | 
				
			||||||
    return nullptr;
 | 
					    return nullptr;
 | 
				
			||||||
 | 
					  CHECK_LE(stack_size, 0x10000000);
 | 
				
			||||||
  uptr old_val = 0;
 | 
					  uptr old_val = 0;
 | 
				
			||||||
  // fake_stack_ has 3 states:
 | 
					  // fake_stack_ has 3 states:
 | 
				
			||||||
  // 0   -- not initialized
 | 
					  // 0   -- not initialized
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,7 +18,7 @@ fi
 | 
				
			||||||
# Filters
 | 
					# Filters
 | 
				
			||||||
# TODO: remove some of these filters
 | 
					# TODO: remove some of these filters
 | 
				
			||||||
COMMON_LINT_FILTER=-build/include,-build/header_guard,-legal/copyright,-whitespace/comments,-readability/casting,\
 | 
					COMMON_LINT_FILTER=-build/include,-build/header_guard,-legal/copyright,-whitespace/comments,-readability/casting,\
 | 
				
			||||||
-build/namespaces
 | 
					-build/namespaces,-readability/braces
 | 
				
			||||||
ASAN_RTL_LINT_FILTER=${COMMON_LINT_FILTER},-runtime/int
 | 
					ASAN_RTL_LINT_FILTER=${COMMON_LINT_FILTER},-runtime/int
 | 
				
			||||||
ASAN_TEST_LINT_FILTER=${COMMON_LINT_FILTER},-runtime/sizeof,-runtime/int,-runtime/printf,-runtime/threadsafe_fn
 | 
					ASAN_TEST_LINT_FILTER=${COMMON_LINT_FILTER},-runtime/sizeof,-runtime/int,-runtime/printf,-runtime/threadsafe_fn
 | 
				
			||||||
ASAN_LIT_TEST_LINT_FILTER=${ASAN_TEST_LINT_FILTER},-whitespace/line_length
 | 
					ASAN_LIT_TEST_LINT_FILTER=${ASAN_TEST_LINT_FILTER},-whitespace/line_length
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,12 +1,13 @@
 | 
				
			||||||
// This test checks that the implementation of use-after-return
 | 
					// This test checks that the implementation of use-after-return
 | 
				
			||||||
// is async-signal-safe.
 | 
					// is async-signal-safe.
 | 
				
			||||||
// RUN: %clangxx_asan -O1 %s -o %t -pthread && %run %t
 | 
					// RUN: %clangxx_asan -std=c++11 -O1 %s -o %t -pthread && %run %t
 | 
				
			||||||
// REQUIRES: stable-runtime
 | 
					// REQUIRES: stable-runtime
 | 
				
			||||||
#include <signal.h>
 | 
					#include <signal.h>
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
#include <sys/time.h>
 | 
					#include <sys/time.h>
 | 
				
			||||||
#include <pthread.h>
 | 
					#include <pthread.h>
 | 
				
			||||||
 | 
					#include <initializer_list>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int *g;
 | 
					int *g;
 | 
				
			||||||
int n_signals;
 | 
					int n_signals;
 | 
				
			||||||
| 
						 | 
					@ -17,7 +18,6 @@ void SignalHandler(int, siginfo_t*, void*) {
 | 
				
			||||||
  int local;
 | 
					  int local;
 | 
				
			||||||
  g = &local;
 | 
					  g = &local;
 | 
				
			||||||
  n_signals++;
 | 
					  n_signals++;
 | 
				
			||||||
  // printf("s: %p\n", &local);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void EnableSigprof(Sigaction SignalHandler) {
 | 
					static void EnableSigprof(Sigaction SignalHandler) {
 | 
				
			||||||
| 
						 | 
					@ -49,22 +49,29 @@ void RecursiveFunction(int depth) {
 | 
				
			||||||
  RecursiveFunction(depth - 1);
 | 
					  RecursiveFunction(depth - 1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void *Thread(void *) {
 | 
					void *FastThread(void *) {
 | 
				
			||||||
  RecursiveFunction(18);
 | 
					  RecursiveFunction(1);
 | 
				
			||||||
 | 
					  return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void *SlowThread(void *) {
 | 
				
			||||||
 | 
					  RecursiveFunction(1);
 | 
				
			||||||
  return NULL;
 | 
					  return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int main(int argc, char **argv) {
 | 
					int main(int argc, char **argv) {
 | 
				
			||||||
  EnableSigprof(SignalHandler);
 | 
					  EnableSigprof(SignalHandler);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  for (int i = 0; i < 4; i++) {
 | 
					  for (auto Thread : {&FastThread, &SlowThread}) {
 | 
				
			||||||
    fprintf(stderr, ".");
 | 
					    for (int i = 0; i < 1000; i++) {
 | 
				
			||||||
    const int kNumThread = sizeof(void*) == 8 ? 16 : 8;
 | 
					      fprintf(stderr, ".");
 | 
				
			||||||
    pthread_t t[kNumThread];
 | 
					      const int kNumThread = sizeof(void*) == 8 ? 32 : 8;
 | 
				
			||||||
    for (int i = 0; i < kNumThread; i++)
 | 
					      pthread_t t[kNumThread];
 | 
				
			||||||
      pthread_create(&t[i], 0, Thread, 0);
 | 
					      for (int i = 0; i < kNumThread; i++)
 | 
				
			||||||
    for (int i = 0; i < kNumThread; i++)
 | 
					        pthread_create(&t[i], 0, Thread, 0);
 | 
				
			||||||
      pthread_join(t[i], 0);
 | 
					      for (int i = 0; i < kNumThread; i++)
 | 
				
			||||||
 | 
					        pthread_join(t[i], 0);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    fprintf(stderr, "\n");
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  fprintf(stderr, "\n");
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue