[PATCH] D17116: [LSan] Fix a crash when LSan hits a guard page while scanning thread stack for pointers.

Alexey Samsonov via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 11 10:11:45 PST 2016


This revision was automatically updated to reflect the committed changes.
Closed by commit rL260554: [LSan] Fix a crash when LSan hits a guard page while scanning thread stackā€¦ (authored by samsonov).

Changed prior to commit:
  http://reviews.llvm.org/D17116?vs=47567&id=47677#toc

Repository:
  rL LLVM

http://reviews.llvm.org/D17116

Files:
  compiler-rt/trunk/lib/lsan/lsan_common.cc
  compiler-rt/trunk/test/lsan/TestCases/guard-page.c

Index: compiler-rt/trunk/lib/lsan/lsan_common.cc
===================================================================
--- compiler-rt/trunk/lib/lsan/lsan_common.cc
+++ compiler-rt/trunk/lib/lsan/lsan_common.cc
@@ -221,9 +221,18 @@
       LOG_THREADS("Stack at %p-%p (SP = %p).\n", stack_begin, stack_end, sp);
       if (sp < stack_begin || sp >= stack_end) {
         // SP is outside the recorded stack range (e.g. the thread is running a
-        // signal handler on alternate stack). Again, consider the entire stack
-        // range to be reachable.
+        // signal handler on alternate stack, or swapcontext was used).
+        // Again, consider the entire stack range to be reachable.
         LOG_THREADS("WARNING: stack pointer not in stack range.\n");
+        uptr page_size = GetPageSizeCached();
+        int skipped = 0;
+        while (stack_begin < stack_end &&
+               !IsAccessibleMemoryRange(stack_begin, 1)) {
+          skipped++;
+          stack_begin += page_size;
+        }
+        LOG_THREADS("Skipped %d guard page(s) to obtain stack %p-%p.\n",
+                    skipped, stack_begin, stack_end);
       } else {
         // Shrink the stack range to ignore out-of-scope values.
         stack_begin = sp;
Index: compiler-rt/trunk/test/lsan/TestCases/guard-page.c
===================================================================
--- compiler-rt/trunk/test/lsan/TestCases/guard-page.c
+++ compiler-rt/trunk/test/lsan/TestCases/guard-page.c
@@ -0,0 +1,60 @@
+// Check that if LSan finds that SP doesn't point into thread stack (e.g.
+// if swapcontext is used), LSan will not hit the guard page.
+// RUN: %clang_lsan %s -o %t && %run %t
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+#include <ucontext.h>
+
+pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+int ctxfunc_started = 0;
+
+static void die(const char* msg, int err) {
+  if (err == 0)
+    err = errno;
+  fprintf(stderr, "%s: %s\n", msg, strerror(err));
+  exit(EXIT_FAILURE);
+}
+
+static void ctxfunc() {
+  pthread_mutex_lock(&mutex);
+  ctxfunc_started = 1;
+  pthread_cond_signal(&cond);
+  pthread_mutex_unlock(&mutex);
+  // Leave this context alive when the program exits.
+  for (;;);
+}
+
+static void* thread(void* arg) {
+  (void)arg;
+  ucontext_t ctx;
+  void* stack;
+
+  if (getcontext(&ctx) < 0)
+    die("getcontext", 0);
+  stack = malloc(1 << 10);
+  if (stack == NULL)
+    die("malloc", 0);
+  ctx.uc_stack.ss_sp = stack;
+  ctx.uc_stack.ss_size = 1 << 10;
+  makecontext(&ctx, ctxfunc, 0);
+  setcontext(&ctx);
+  die("setcontext", 0);
+  return NULL;
+}
+
+int main() {
+  pthread_t tid;
+  int i;
+
+  pthread_mutex_lock(&mutex);
+  i = pthread_create(&tid, NULL, thread, NULL);
+  if (i != 0)
+    die("pthread_create", i);
+  while (!ctxfunc_started) pthread_cond_wait(&cond, &mutex);
+  pthread_mutex_unlock(&mutex);
+  return 0;
+}


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D17116.47677.patch
Type: text/x-patch
Size: 2980 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160211/0bef8967/attachment.bin>


More information about the llvm-commits mailing list