andriigrynenko updated this revision to Diff 72571.
andriigrynenko added a comment.
Do CHECKs for all iterations of the loop.


https://reviews.llvm.org/D24628

Files:
  include/sanitizer/common_interface_defs.h
  lib/asan/asan_thread.cc
  lib/asan/asan_thread.h
  test/asan/TestCases/Linux/swapcontext_annotation.cc

Index: test/asan/TestCases/Linux/swapcontext_annotation.cc
===================================================================
--- test/asan/TestCases/Linux/swapcontext_annotation.cc
+++ test/asan/TestCases/Linux/swapcontext_annotation.cc
@@ -1,12 +1,17 @@
 // Check that ASan plays well with annotated makecontext/swapcontext.
 
-// RUN: %clangxx_asan -lpthread -O0 %s -o %t && %run %t 2>&1 | FileCheck %s
-// RUN: %clangxx_asan -lpthread -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
-// RUN: %clangxx_asan -lpthread -O2 %s -o %t && %run %t 2>&1 | FileCheck %s
-// RUN: %clangxx_asan -lpthread -O3 %s -o %t && %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -std=c++11 -lpthread -O0 %s -o %t && %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -std=c++11 -lpthread -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -std=c++11 -lpthread -O2 %s -o %t && %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -std=c++11 -lpthread -O3 %s -o %t && %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -std=c++11 -lpthread -O0 %s -o %t && %run %t 2>&1 | FileCheck <( seq 60 | xargs -i -- grep LOOPCHECK %s ) --check-prefix LOOPCHECK
+// RUN: %clangxx_asan -std=c++11 -lpthread -O1 %s -o %t && %run %t 2>&1 | FileCheck <( seq 60 | xargs -i -- grep LOOPCHECK %s ) --check-prefix LOOPCHECK
+// RUN: %clangxx_asan -std=c++11 -lpthread -O2 %s -o %t && %run %t 2>&1 | FileCheck <( seq 60 | xargs -i -- grep LOOPCHECK %s ) --check-prefix LOOPCHECK
+// RUN: %clangxx_asan -std=c++11 -lpthread -O3 %s -o %t && %run %t 2>&1 | FileCheck <( seq 60 | xargs -i -- grep LOOPCHECK %s ) --check-prefix LOOPCHECK
+
 //
 // This test is too subtle to try on non-x86 arch for now.
-// REQUIRES: x86_64-supported-target,i386-supported-target
+// REQUIRES: x86-target-arch
 
 #include <pthread.h>
 #include <setjmp.h>
@@ -25,9 +30,12 @@
 
 const int kStackSize = 1 << 20;
 
-void *main_thread_stack;
+const void *main_thread_stack;
 size_t main_thread_stacksize;
 
+const void *from_stack;
+size_t from_stacksize;
+
 __attribute__((noinline, noreturn)) void LongJump(jmp_buf env) {
   longjmp(env, 1);
   _exit(1);
@@ -44,14 +52,18 @@
 
 void NextChild() {
   CallNoReturn();
-  __sanitizer_finish_switch_fiber();
+  __sanitizer_finish_switch_fiber(nullptr, &from_stack, &from_stacksize);
+
+  printf("NextChild from: %p %zu\n", from_stack, from_stacksize);
 
   char x[32] = {0};  // Stack gets poisoned.
   printf("NextChild: %p\n", x);
 
   CallNoReturn();
 
-  __sanitizer_start_switch_fiber(main_thread_stack, main_thread_stacksize);
+  __sanitizer_start_switch_fiber(nullptr,
+                                 main_thread_stack,
+                                 main_thread_stacksize);
   CallNoReturn();
   if (swapcontext(&next_child_context, &orig_context) < 0) {
     perror("swapcontext");
@@ -61,30 +73,39 @@
 
 void Child(int mode) {
   CallNoReturn();
-  __sanitizer_finish_switch_fiber();
+  __sanitizer_finish_switch_fiber(nullptr,
+                                  &main_thread_stack,
+                                  &main_thread_stacksize);
   char x[32] = {0};  // Stack gets poisoned.
   printf("Child: %p\n", x);
   CallNoReturn();
   // (a) Do nothing, just return to parent function.
   // (b) Jump into the original function. Stack remains poisoned unless we do
   //     something.
   // (c) Jump to another function which will then jump back to the main function
   if (mode == 0) {
-    __sanitizer_start_switch_fiber(main_thread_stack, main_thread_stacksize);
+    __sanitizer_start_switch_fiber(nullptr,
+                                   main_thread_stack,
+                                   main_thread_stacksize);
     CallNoReturn();
   } else if (mode == 1) {
-    __sanitizer_start_switch_fiber(main_thread_stack, main_thread_stacksize);
+    __sanitizer_start_switch_fiber(nullptr,
+                                   main_thread_stack,
+                                   main_thread_stacksize);
     CallNoReturn();
     if (swapcontext(&child_context, &orig_context) < 0) {
       perror("swapcontext");
       _exit(1);
     }
   } else if (mode == 2) {
+    printf("NextChild stack: %p\n", next_child_stack);
+
     getcontext(&next_child_context);
     next_child_context.uc_stack.ss_sp = next_child_stack;
     next_child_context.uc_stack.ss_size = kStackSize / 2;
     makecontext(&next_child_context, (void (*)())NextChild, 0);
-    __sanitizer_start_switch_fiber(next_child_context.uc_stack.ss_sp,
+    __sanitizer_start_switch_fiber(nullptr,
+                                   next_child_context.uc_stack.ss_sp,
                                    next_child_context.uc_stack.ss_size);
     CallNoReturn();
     if (swapcontext(&child_context, &next_child_context) < 0) {
@@ -105,16 +126,21 @@
   }
   makecontext(&child_context, (void (*)())Child, 1, mode);
   CallNoReturn();
-  __sanitizer_start_switch_fiber(child_context.uc_stack.ss_sp,
+  void* fake_stack_save;
+  __sanitizer_start_switch_fiber(&fake_stack_save,
+                                 child_context.uc_stack.ss_sp,
                                  child_context.uc_stack.ss_size);
   CallNoReturn();
   if (swapcontext(&orig_context, &child_context) < 0) {
     perror("swapcontext");
     _exit(1);
   }
   CallNoReturn();
-  __sanitizer_finish_switch_fiber();
+  __sanitizer_finish_switch_fiber(fake_stack_save,
+                                  &from_stack,
+                                  &from_stacksize);
   CallNoReturn();
+  printf("Main context from: %p %zu\n", from_stack, from_stacksize);
 
   // Touch childs's stack to make sure it's unpoisoned.
   for (int i = 0; i < kStackSize; i++) {
@@ -125,17 +151,7 @@
 
 void handler(int sig) { CallNoReturn(); }
 
-void InitStackBounds() {
-  pthread_attr_t attr;
-  pthread_attr_init(&attr);
-  pthread_getattr_np(pthread_self(), &attr);
-  pthread_attr_getstack(&attr, &main_thread_stack, &main_thread_stacksize);
-  pthread_attr_destroy(&attr);
-}
-
 int main(int argc, char **argv) {
-  InitStackBounds();
-
   // set up a signal that will spam and trigger __asan_handle_no_return at
   // tricky moments
   struct sigaction act = {};
@@ -162,12 +178,22 @@
   // CHECK-NOT: ASan is ignoring requested __asan_handle_no_return
   for (unsigned int i = 0; i < 30; ++i) {
     ret += Run(argc - 1, 0, stack);
+    // LOOPCHECK: Child stack: [[CHILD_STACK:0x[0-9a-f]*]]
+    // LOOPCHECK: Main context from: [[CHILD_STACK]] 524288
     ret += Run(argc - 1, 1, stack);
+    // LOOPCHECK: Child stack: [[CHILD_STACK:0x[0-9a-f]*]]
+    // LOOPCHECK: Main context from: [[CHILD_STACK]] 524288
     ret += Run(argc - 1, 2, stack);
+    // LOOPCHECK: Child stack: [[CHILD_STACK:0x[0-9a-f]*]]
+    // LOOPCHECK: NextChild stack: [[NEXT_CHILD_STACK:0x[0-9a-f]*]]
+    // LOOPCHECK: NextChild from: [[CHILD_STACK]] 524288
+    // LOOPCHECK: Main context from: [[NEXT_CHILD_STACK]] 524288
     ret += Run(argc - 1, 0, heap);
     ret += Run(argc - 1, 1, heap);
     ret += Run(argc - 1, 2, heap);
+    printf("Iteration %d passed\n", i);
   }
+
   // CHECK: Test passed
   printf("Test passed\n");
 
Index: lib/asan/asan_thread.h
===================================================================
--- lib/asan/asan_thread.h
+++ lib/asan/asan_thread.h
@@ -94,7 +94,8 @@
   }
 
   void StartSwitchFiber(FakeStack **fake_stack_save, uptr bottom, uptr size);
-  void FinishSwitchFiber(FakeStack *fake_stack_save);
+  void FinishSwitchFiber(FakeStack *fake_stack_save, uptr *bottom_old,
+                         uptr *size_old);
 
   bool has_fake_stack() {
     return !atomic_load(&stack_switching_, memory_order_relaxed) &&
Index: lib/asan/asan_thread.cc
===================================================================
--- lib/asan/asan_thread.cc
+++ lib/asan/asan_thread.cc
@@ -141,7 +141,9 @@
     current_fake_stack->Destroy(this->tid());
 }
 
-void AsanThread::FinishSwitchFiber(FakeStack *fake_stack_save) {
+void AsanThread::FinishSwitchFiber(FakeStack *fake_stack_save,
+                                   uptr *bottom_old,
+                                   uptr *size_old) {
   if (!atomic_load(&stack_switching_, memory_order_relaxed)) {
     Report("ERROR: finishing a fiber switch that has not started\n");
     Die();
@@ -152,6 +154,10 @@
     fake_stack_ = fake_stack_save;
   }
 
+  if (bottom_old)
+    *bottom_old = stack_bottom_;
+  if (size_old)
+    *size_old = stack_top_ - stack_bottom_;
   stack_bottom_ = next_stack_bottom_;
   stack_top_ = next_stack_top_;
   atomic_store(&stack_switching_, 0, memory_order_release);
@@ -447,12 +453,16 @@
 }
 
 SANITIZER_INTERFACE_ATTRIBUTE
-void __sanitizer_finish_switch_fiber(void* fakestack) {
+void __sanitizer_finish_switch_fiber(void* fakestack,
+                                     const void **bottom_old,
+                                     uptr *size_old) {
   AsanThread *t = GetCurrentThread();
   if (!t) {
     VReport(1, "__asan_finish_switch_fiber called from unknown thread\n");
     return;
   }
-  t->FinishSwitchFiber((FakeStack*)fakestack);
+  t->FinishSwitchFiber((FakeStack*)fakestack,
+                       (uptr*)bottom_old,
+                       (uptr*)size_old);
 }
 }
Index: include/sanitizer/common_interface_defs.h
===================================================================
--- include/sanitizer/common_interface_defs.h
+++ include/sanitizer/common_interface_defs.h
@@ -176,7 +176,9 @@
   // use-after-return detection.
   void __sanitizer_start_switch_fiber(void **fake_stack_save,
                                       const void *bottom, size_t size);
-  void __sanitizer_finish_switch_fiber(void *fake_stack_save);
+  void __sanitizer_finish_switch_fiber(void *fake_stack_save,
+                                       const void **bottom_old,
+                                       size_t *size_old);
 #ifdef __cplusplus
 }  // extern "C"
 #endif
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to