1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
|
/*
* Copyright (C) 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "StructuredExceptionHandlerSuppressor.h"
#if defined(_M_IX86)
extern "C" int __stdcall exceptionHandlerThunk(); // Defined in makesafeseh.asm
#endif
static bool exceptionShouldTerminateProgram(int code)
{
switch (code) {
#ifndef NDEBUG
case EXCEPTION_DATATYPE_MISALIGNMENT:
case EXCEPTION_FLT_DENORMAL_OPERAND:
case EXCEPTION_FLT_DIVIDE_BY_ZERO:
case EXCEPTION_FLT_INEXACT_RESULT:
case EXCEPTION_FLT_INVALID_OPERATION:
case EXCEPTION_FLT_OVERFLOW:
case EXCEPTION_FLT_STACK_CHECK:
case EXCEPTION_FLT_UNDERFLOW:
#endif
case EXCEPTION_ACCESS_VIOLATION:
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
case EXCEPTION_INT_DIVIDE_BY_ZERO:
case EXCEPTION_INT_OVERFLOW:
case EXCEPTION_PRIV_INSTRUCTION:
case EXCEPTION_IN_PAGE_ERROR:
case EXCEPTION_ILLEGAL_INSTRUCTION:
case EXCEPTION_NONCONTINUABLE_EXCEPTION:
case EXCEPTION_STACK_OVERFLOW:
case EXCEPTION_INVALID_DISPOSITION:
case EXCEPTION_GUARD_PAGE:
case EXCEPTION_INVALID_HANDLE:
return true;
};
return false;
}
extern "C" EXCEPTION_DISPOSITION __stdcall exceptionHandler(struct _EXCEPTION_RECORD* exceptionRecord, void* /*establisherFrame*/, struct _CONTEXT* /*contextRecord*/, void* /*dispatcherContext*/)
{
if (exceptionShouldTerminateProgram(exceptionRecord->ExceptionCode))
abort();
return ExceptionContinueSearch;
}
namespace WebCore {
#pragma warning(push)
#pragma warning(disable: 4733) // Disable "not registered as safe handler" warning
StructuredExceptionHandlerSuppressor::StructuredExceptionHandlerSuppressor(ExceptionRegistration& exceptionRegistration)
{
#if defined(_M_IX86)
// Note: Windows requires that the EXCEPTION_REGISTRATION block (modeled here as our
// ExceptionRegistration struct) be stack allocated. Therefore we instantiated it prior
// to building this object so that Windows can still find it in stack memory when it
// attempts to use the handler.
// Windows puts an __try/__except block around some calls, such as hooks.
// The exception handler then ignores system exceptions like invalid addresses
// and null pointers. This class can be used to remove this block and prevent
// it from catching the exception. Typically this will cause the exception to crash
// which is often desirable to allow crashlogs to be recorded for debugging purposed.
// While this class is in scope we replace the Windows exception handler with a custom
// handler that indicates exceptions that should not be handled.
//
// See http://www.microsoft.com/msj/0197/Exception/Exception.aspx,
// http://www.microsoft.com/msj/archive/S2CE.aspx
// http://www.hexblog.com/wp-content/uploads/2012/06/Recon-2012-Skochinsky-Compiler-Internals.pdf
// http://www.codeproject.com/Articles/2126/How-a-C-compiler-implements-exception-handling
// Windows doesn't like assigning to member variables, so we need to get the value into
// a local variable and store it afterwards.
void* registration;
// Note: The FS register on Windows always holds the Thread Information Block.
// FS:[0] points to the structured exception handling chain (a chain of
// EXCEPTION_REGISTRATION structs).
//
// struct EXCEPTION_REGISTRATION
// {
// DWORD next;
// DWORD handler;
// };
//
// The first four bytes of FS:[0] point to the 'Next' member in the chain. Grab it so we can restore it later.
__asm mov eax, FS:[0]
__asm mov [registration], eax
exceptionRegistration.prev = (ExceptionRegistration*)registration;
exceptionRegistration.handler = (void*)exceptionHandlerThunk;
void* erStructMem = &exceptionRegistration;
__asm mov eax, erStructMem
__asm mov FS:[0], eax
m_savedExceptionRegistration = registration;
#else
// 64-bit x64 no longer needs dynamic modification of the exception handlers.
#endif
}
StructuredExceptionHandlerSuppressor::~StructuredExceptionHandlerSuppressor()
{
#if defined(_M_IX86)
// Restore the exception handler
__asm mov eax, [m_savedExceptionRegistration]
__asm mov FS:[0], eax
#else
#endif
}
#pragma warning(pop)
}
|