[asan] Intercept SetUnhandledExceptionFilter.
In this diff I update the code for asan on Windows, so we can intercept SetUnhandledExceptionFilter and catch some exceptions depending on the result of IsHandledDeadlyException() (which depends on asan flags). This way we have the same behavior on Windows and Posix systems. On Posix, we intercept signal and sigaction, so user's code can only register signal handlers for signals that are not handled by asan. After this diff, the same happens on Windows, user's code can only register exception handlers for exceptions that are not handled by asan. Differential Revision: https://reviews.llvm.org/D29463 llvm-svn: 293957
This commit is contained in:
parent
fe9288a6a0
commit
e49ec6d57c
|
@ -47,6 +47,47 @@ uptr __asan_get_shadow_memory_dynamic_address() {
|
|||
} // extern "C"
|
||||
|
||||
// ---------------------- Windows-specific interceptors ---------------- {{{
|
||||
static LPTOP_LEVEL_EXCEPTION_FILTER default_seh_handler;
|
||||
static LPTOP_LEVEL_EXCEPTION_FILTER user_seh_handler;
|
||||
|
||||
extern "C" SANITIZER_INTERFACE_ATTRIBUTE
|
||||
long __asan_unhandled_exception_filter(EXCEPTION_POINTERS *info) {
|
||||
EXCEPTION_RECORD *exception_record = info->ExceptionRecord;
|
||||
CONTEXT *context = info->ContextRecord;
|
||||
|
||||
// FIXME: Handle EXCEPTION_STACK_OVERFLOW here.
|
||||
|
||||
SignalContext sig = SignalContext::Create(exception_record, context);
|
||||
ReportDeadlySignal(exception_record->ExceptionCode, sig);
|
||||
UNREACHABLE("returned from reporting deadly signal");
|
||||
}
|
||||
|
||||
// Wrapper SEH Handler. If the exception should be handled by asan, we call
|
||||
// __asan_unhandled_exception_filter, otherwise, we execute the user provided
|
||||
// exception handler or the default.
|
||||
static long WINAPI SEHHandler(EXCEPTION_POINTERS *info) {
|
||||
DWORD exception_code = info->ExceptionRecord->ExceptionCode;
|
||||
if (__sanitizer::IsHandledDeadlyException(exception_code))
|
||||
return __asan_unhandled_exception_filter(info);
|
||||
if (user_seh_handler)
|
||||
return user_seh_handler(info);
|
||||
// Bubble out to the default exception filter.
|
||||
if (default_seh_handler)
|
||||
return default_seh_handler(info);
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
|
||||
INTERCEPTOR_WINAPI(LPTOP_LEVEL_EXCEPTION_FILTER, SetUnhandledExceptionFilter,
|
||||
LPTOP_LEVEL_EXCEPTION_FILTER ExceptionFilter) {
|
||||
CHECK(REAL(SetUnhandledExceptionFilter));
|
||||
if (ExceptionFilter == &SEHHandler || common_flags()->allow_user_segv_handler)
|
||||
return REAL(SetUnhandledExceptionFilter)(ExceptionFilter);
|
||||
// We record the user provided exception handler to be called for all the
|
||||
// exceptions unhandled by asan.
|
||||
Swap(ExceptionFilter, user_seh_handler);
|
||||
return ExceptionFilter;
|
||||
}
|
||||
|
||||
INTERCEPTOR_WINAPI(void, RtlRaiseException, EXCEPTION_RECORD *ExceptionRecord) {
|
||||
CHECK(REAL(RtlRaiseException));
|
||||
// This is a noreturn function, unless it's one of the exceptions raised to
|
||||
|
@ -119,6 +160,7 @@ namespace __asan {
|
|||
|
||||
void InitializePlatformInterceptors() {
|
||||
ASAN_INTERCEPT_FUNC(CreateThread);
|
||||
ASAN_INTERCEPT_FUNC(SetUnhandledExceptionFilter);
|
||||
|
||||
#ifdef _WIN64
|
||||
ASAN_INTERCEPT_FUNC(__C_specific_handler);
|
||||
|
@ -235,30 +277,6 @@ void InitializePlatformExceptionHandlers() {
|
|||
#endif
|
||||
}
|
||||
|
||||
static LPTOP_LEVEL_EXCEPTION_FILTER default_seh_handler;
|
||||
|
||||
extern "C" SANITIZER_INTERFACE_ATTRIBUTE
|
||||
long __asan_unhandled_exception_filter(EXCEPTION_POINTERS *info) {
|
||||
EXCEPTION_RECORD *exception_record = info->ExceptionRecord;
|
||||
CONTEXT *context = info->ContextRecord;
|
||||
|
||||
// Continue the search if the signal wasn't deadly.
|
||||
if (!IsHandledDeadlyException(exception_record->ExceptionCode))
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
// FIXME: Handle EXCEPTION_STACK_OVERFLOW here.
|
||||
|
||||
SignalContext sig = SignalContext::Create(exception_record, context);
|
||||
ReportDeadlySignal(exception_record->ExceptionCode, sig);
|
||||
UNREACHABLE("returned from reporting deadly signal");
|
||||
}
|
||||
|
||||
static long WINAPI SEHHandler(EXCEPTION_POINTERS *info) {
|
||||
__asan_unhandled_exception_filter(info);
|
||||
|
||||
// Bubble out to the default exception filter.
|
||||
return default_seh_handler(info);
|
||||
}
|
||||
|
||||
// We want to install our own exception handler (EH) to print helpful reports
|
||||
// on access violations and whatnot. Unfortunately, the CRT initializers assume
|
||||
// they are run before any user code and drop any previously-installed EHs on
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
// IMPORT: __asan_wrap_CreateThread
|
||||
// IMPORT: __asan_wrap_RaiseException
|
||||
// IMPORT: __asan_wrap_RtlRaiseException
|
||||
// IMPORT: __asan_wrap_SetUnhandledExceptionFilter
|
||||
//
|
||||
// RUN: cat %t.imports1 %t.imports2 | sort | uniq > %t.imports-sorted
|
||||
// RUN: cat %t.exports1 %t.exports2 | sort | uniq > %t.exports-sorted
|
||||
|
|
Loading…
Reference in New Issue