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))
|
(code == si_SEGV_MAPERR || code == si_SEGV_ACCERR))
|
||||||
ReportStackOverflow(pc, sp, bp, context, addr);
|
ReportStackOverflow(pc, sp, bp, context, addr);
|
||||||
else
|
else
|
||||||
ReportSIGSEGV(pc, sp, bp, context, addr);
|
ReportSIGSEGV("SEGV", pc, sp, bp, context, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------- TSD ---------------- {{{1
|
// ---------------------- TSD ---------------- {{{1
|
||||||
|
|
|
||||||
|
|
@ -611,14 +611,15 @@ void ReportStackOverflow(uptr pc, uptr sp, uptr bp, void *context, uptr addr) {
|
||||||
ReportErrorSummary("stack-overflow", &stack);
|
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;
|
ScopedInErrorReport in_report;
|
||||||
Decorator d;
|
Decorator d;
|
||||||
Printf("%s", d.Warning());
|
Printf("%s", d.Warning());
|
||||||
Report(
|
Report(
|
||||||
"ERROR: AddressSanitizer: SEGV on unknown address %p"
|
"ERROR: AddressSanitizer: %s on unknown address %p"
|
||||||
" (pc %p sp %p bp %p T%d)\n",
|
" (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());
|
GetCurrentTidOrInvalid());
|
||||||
Printf("%s", d.EndWarning());
|
Printf("%s", d.EndWarning());
|
||||||
GET_STACK_TRACE_SIGNAL(pc, bp, context);
|
GET_STACK_TRACE_SIGNAL(pc, bp, context);
|
||||||
|
|
|
||||||
|
|
@ -34,8 +34,8 @@ void DescribeThread(AsanThreadContext *context);
|
||||||
// Different kinds of error reports.
|
// Different kinds of error reports.
|
||||||
void NORETURN
|
void NORETURN
|
||||||
ReportStackOverflow(uptr pc, uptr sp, uptr bp, void *context, uptr addr);
|
ReportStackOverflow(uptr pc, uptr sp, uptr bp, void *context, uptr addr);
|
||||||
void NORETURN
|
void NORETURN ReportSIGSEGV(const char *description, uptr pc, uptr sp, uptr bp,
|
||||||
ReportSIGSEGV(uptr pc, uptr sp, uptr bp, void *context, uptr addr);
|
void *context, uptr addr);
|
||||||
void NORETURN ReportDoubleFree(uptr addr, StackTrace *free_stack);
|
void NORETURN ReportDoubleFree(uptr addr, StackTrace *free_stack);
|
||||||
void NORETURN ReportFreeNotMalloced(uptr addr, StackTrace *free_stack);
|
void NORETURN ReportFreeNotMalloced(uptr addr, StackTrace *free_stack);
|
||||||
void NORETURN ReportAllocTypeMismatch(uptr addr, StackTrace *free_stack,
|
void NORETURN ReportAllocTypeMismatch(uptr addr, StackTrace *free_stack,
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
#include "asan_interceptors.h"
|
#include "asan_interceptors.h"
|
||||||
#include "asan_internal.h"
|
#include "asan_internal.h"
|
||||||
|
#include "asan_report.h"
|
||||||
#include "asan_thread.h"
|
#include "asan_thread.h"
|
||||||
#include "sanitizer_common/sanitizer_libc.h"
|
#include "sanitizer_common/sanitizer_libc.h"
|
||||||
#include "sanitizer_common/sanitizer_mutex.h"
|
#include "sanitizer_common/sanitizer_mutex.h"
|
||||||
|
|
@ -86,6 +87,44 @@ void AsanOnSIGSEGV(int, void *siginfo, void *context) {
|
||||||
UNIMPLEMENTED();
|
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
|
} // namespace __asan
|
||||||
|
|
||||||
#endif // _WIN32
|
#endif // _WIN32
|
||||||
|
|
|
||||||
|
|
@ -17,9 +17,10 @@
|
||||||
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#define NOGDI
|
#define NOGDI
|
||||||
#include <stdlib.h>
|
|
||||||
#include <io.h>
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#include <dbghelp.h>
|
||||||
|
#include <io.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "sanitizer_common.h"
|
#include "sanitizer_common.h"
|
||||||
#include "sanitizer_libc.h"
|
#include "sanitizer_libc.h"
|
||||||
|
|
@ -449,7 +450,30 @@ void StackTrace::SlowUnwindStack(uptr pc, uptr max_depth) {
|
||||||
|
|
||||||
void StackTrace::SlowUnwindStackWithContext(uptr pc, void *context,
|
void StackTrace::SlowUnwindStackWithContext(uptr pc, void *context,
|
||||||
uptr max_depth) {
|
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() {
|
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