File: StructuredExceptionHandlerSuppressor.cpp

package info (click to toggle)
qtwebkit-opensource-src 5.212.0~alpha4-11
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 126,228 kB
  • sloc: cpp: 1,399,205; javascript: 111,961; ansic: 29,742; perl: 19,510; python: 13,364; ruby: 10,299; xml: 9,342; asm: 5,078; yacc: 2,166; lex: 906; sh: 417; makefile: 34
file content (143 lines) | stat: -rw-r--r-- 5,552 bytes parent folder | download | duplicates (3)
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)

}