forked from OSchip/llvm-project
				
			[ASan/Win] Catch NULL derefs and page faults
Reviewed at http://reviews.llvm.org/D4471 llvm-svn: 212807
This commit is contained in:
		
							parent
							
								
									1028ae7441
								
							
						
					
					
						commit
						19853dd28c
					
				| 
						 | 
				
			
			@ -50,7 +50,7 @@ void AsanOnSIGSEGV(int, void *siginfo, void *context) {
 | 
			
		|||
      (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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -611,14 +611,15 @@ void ReportStackOverflow(uptr pc, uptr sp, uptr bp, void *context, uptr addr) {
 | 
			
		|||
  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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,8 +34,8 @@ void DescribeThread(AsanThreadContext *context);
 | 
			
		|||
// 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,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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, void *context) {
 | 
			
		|||
  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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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, uptr max_depth) {
 | 
			
		|||
 | 
			
		||||
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() {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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.}}
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue