[compiler-rt] r212807 - [ASan/Win] Catch NULL derefs and page faults

Timur Iskhodzhanov timurrrr at google.com
Fri Jul 11 04:57:42 PDT 2014


Author: timurrrr
Date: Fri Jul 11 06:57:41 2014
New Revision: 212807

URL: http://llvm.org/viewvc/llvm-project?rev=212807&view=rev
Log:
[ASan/Win] Catch NULL derefs and page faults

Reviewed at http://reviews.llvm.org/D4471

Added:
    compiler-rt/trunk/test/asan/TestCases/Windows/null_deref.cc
Modified:
    compiler-rt/trunk/lib/asan/asan_posix.cc
    compiler-rt/trunk/lib/asan/asan_report.cc
    compiler-rt/trunk/lib/asan/asan_report.h
    compiler-rt/trunk/lib/asan/asan_win.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc

Modified: compiler-rt/trunk/lib/asan/asan_posix.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_posix.cc?rev=212807&r1=212806&r2=212807&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_posix.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_posix.cc Fri Jul 11 06:57:41 2014
@@ -50,7 +50,7 @@ void AsanOnSIGSEGV(int, void *siginfo, v
       (code == si_SEGV_MAPERR || code == si_SEGV_ACCERR))
     ReportStackOverflow(pc, sp, bp, context, addr);
   else
-    ReportSIGSEGV(pc, sp, bp, context, addr);
+    ReportSIGSEGV("SEGV", pc, sp, bp, context, addr);
 }
 
 // ---------------------- TSD ---------------- {{{1

Modified: compiler-rt/trunk/lib/asan/asan_report.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_report.cc?rev=212807&r1=212806&r2=212807&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_report.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_report.cc Fri Jul 11 06:57:41 2014
@@ -611,14 +611,15 @@ void ReportStackOverflow(uptr pc, uptr s
   ReportErrorSummary("stack-overflow", &stack);
 }
 
-void ReportSIGSEGV(uptr pc, uptr sp, uptr bp, void *context, uptr addr) {
+void ReportSIGSEGV(const char *description, uptr pc, uptr sp, uptr bp,
+                   void *context, uptr addr) {
   ScopedInErrorReport in_report;
   Decorator d;
   Printf("%s", d.Warning());
   Report(
-      "ERROR: AddressSanitizer: SEGV on unknown address %p"
+      "ERROR: AddressSanitizer: %s on unknown address %p"
       " (pc %p sp %p bp %p T%d)\n",
-      (void *)addr, (void *)pc, (void *)sp, (void *)bp,
+      description, (void *)addr, (void *)pc, (void *)sp, (void *)bp,
       GetCurrentTidOrInvalid());
   Printf("%s", d.EndWarning());
   GET_STACK_TRACE_SIGNAL(pc, bp, context);

Modified: compiler-rt/trunk/lib/asan/asan_report.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_report.h?rev=212807&r1=212806&r2=212807&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_report.h (original)
+++ compiler-rt/trunk/lib/asan/asan_report.h Fri Jul 11 06:57:41 2014
@@ -34,8 +34,8 @@ void DescribeThread(AsanThreadContext *c
 // Different kinds of error reports.
 void NORETURN
     ReportStackOverflow(uptr pc, uptr sp, uptr bp, void *context, uptr addr);
-void NORETURN
-    ReportSIGSEGV(uptr pc, uptr sp, uptr bp, void *context, uptr addr);
+void NORETURN ReportSIGSEGV(const char *description, uptr pc, uptr sp, uptr bp,
+                            void *context, uptr addr);
 void NORETURN ReportDoubleFree(uptr addr, StackTrace *free_stack);
 void NORETURN ReportFreeNotMalloced(uptr addr, StackTrace *free_stack);
 void NORETURN ReportAllocTypeMismatch(uptr addr, StackTrace *free_stack,

Modified: compiler-rt/trunk/lib/asan/asan_win.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_win.cc?rev=212807&r1=212806&r2=212807&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_win.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_win.cc Fri Jul 11 06:57:41 2014
@@ -21,6 +21,7 @@
 
 #include "asan_interceptors.h"
 #include "asan_internal.h"
+#include "asan_report.h"
 #include "asan_thread.h"
 #include "sanitizer_common/sanitizer_libc.h"
 #include "sanitizer_common/sanitizer_mutex.h"
@@ -86,6 +87,44 @@ void AsanOnSIGSEGV(int, void *siginfo, v
   UNIMPLEMENTED();
 }
 
+static LPTOP_LEVEL_EXCEPTION_FILTER default_seh_handler;
+
+long WINAPI SEHHandler(EXCEPTION_POINTERS *info) {
+  EXCEPTION_RECORD *exception_record = info->ExceptionRecord;
+  CONTEXT *context = info->ContextRecord;
+  uptr pc = (uptr)exception_record->ExceptionAddress;
+#ifdef _WIN64
+  uptr bp = (uptr)context->Rbp, sp = (uptr)context->Rsp;
+#else
+  uptr bp = (uptr)context->Ebp, sp = (uptr)context->Esp;
+#endif
+
+  if (exception_record->ExceptionCode == EXCEPTION_ACCESS_VIOLATION ||
+      exception_record->ExceptionCode == EXCEPTION_IN_PAGE_ERROR) {
+    const char *description =
+        (exception_record->ExceptionCode == EXCEPTION_ACCESS_VIOLATION)
+            ? "access-violation"
+            : "in-page-error";
+    uptr access_addr = exception_record->ExceptionInformation[1];
+    ReportSIGSEGV(description, pc, sp, bp, context, access_addr);
+  }
+
+  // FIXME: Handle EXCEPTION_STACK_OVERFLOW here.
+
+  return default_seh_handler(info);
+}
+
+int SetSEHFilter() {
+  default_seh_handler = SetUnhandledExceptionFilter(SEHHandler);
+  return 0;
+}
+
+// Put a pointer to SetSEHFilter at the end of the global list
+// of C initializers, after the default handler is set by the CRT.
+// See crt0dat.c in the CRT sources for the details.
+#pragma section(".CRT$XIZ", long, read)  // NOLINT
+__declspec(allocate(".CRT$XIZ")) int (*__intercept_seh)() = SetSEHFilter;
+
 }  // namespace __asan
 
 #endif  // _WIN32

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc?rev=212807&r1=212806&r2=212807&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc Fri Jul 11 06:57:41 2014
@@ -17,9 +17,10 @@
 
 #define WIN32_LEAN_AND_MEAN
 #define NOGDI
-#include <stdlib.h>
-#include <io.h>
 #include <windows.h>
+#include <dbghelp.h>
+#include <io.h>
+#include <stdlib.h>
 
 #include "sanitizer_common.h"
 #include "sanitizer_libc.h"
@@ -449,7 +450,30 @@ void StackTrace::SlowUnwindStack(uptr pc
 
 void StackTrace::SlowUnwindStackWithContext(uptr pc, void *context,
                                             uptr max_depth) {
-  UNREACHABLE("no signal context on windows");
+  CONTEXT ctx = *(CONTEXT *)context;
+  STACKFRAME64 stack_frame;
+  memset(&stack_frame, 0, sizeof(stack_frame));
+  size = 0;
+#if defined(_WIN64)
+  int machine_type = IMAGE_FILE_MACHINE_AMD64;
+  stack_frame.AddrPC.Offset = ctx.Rip;
+  stack_frame.AddrFrame.Offset = ctx.Rbp;
+  stack_frame.AddrStack.Offset = ctx.Rsp;
+#else
+  int machine_type = IMAGE_FILE_MACHINE_I386;
+  stack_frame.AddrPC.Offset = ctx.Eip;
+  stack_frame.AddrFrame.Offset = ctx.Ebp;
+  stack_frame.AddrStack.Offset = ctx.Esp;
+#endif
+  stack_frame.AddrPC.Mode = AddrModeFlat;
+  stack_frame.AddrFrame.Mode = AddrModeFlat;
+  stack_frame.AddrStack.Mode = AddrModeFlat;
+  while (StackWalk64(machine_type, GetCurrentProcess(), GetCurrentThread(),
+                     &stack_frame, &ctx, NULL, &SymFunctionTableAccess64,
+                     &SymGetModuleBase64, NULL) &&
+         size < Min(max_depth, kStackTraceMax)) {
+    trace[size++] = (uptr)stack_frame.AddrPC.Offset;
+  }
 }
 
 void MaybeOpenReportFile() {

Added: compiler-rt/trunk/test/asan/TestCases/Windows/null_deref.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/Windows/null_deref.cc?rev=212807&view=auto
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/Windows/null_deref.cc (added)
+++ compiler-rt/trunk/test/asan/TestCases/Windows/null_deref.cc Fri Jul 11 06:57:41 2014
@@ -0,0 +1,15 @@
+// RUN: %clangxx_asan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK
+// FIXME: merge this with the common null_deref test when we can run common
+// tests on Windows.
+
+__attribute__((noinline))
+static void NullDeref(int *ptr) {
+  // CHECK: ERROR: AddressSanitizer: access-violation on unknown address
+  // CHECK:   {{0x0*000.. .*pc 0x.*}}
+  ptr[10]++;  // BOOM
+}
+int main() {
+  NullDeref((int*)0);
+  // CHECK: {{    #1 0x.* in main.*null_deref.cc:}}[[@LINE-1]]
+  // CHECK: {{AddressSanitizer can not provide additional info.}}
+}





More information about the llvm-commits mailing list