summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrobertshield@chromium.org <robertshield@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-05-01 02:10:06 +0000
committerrobertshield@chromium.org <robertshield@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-05-01 02:10:06 +0000
commit72354315dd3c9682370ee2eea62446b7e5539990 (patch)
tree4f8be23e6d8ec76c7d537ca693815a7405cf2f02
parentc96c3c973c12f552ed6abd565fd326c32c227a5f (diff)
downloadchromium_src-72354315dd3c9682370ee2eea62446b7e5539990.zip
chromium_src-72354315dd3c9682370ee2eea62446b7e5539990.tar.gz
chromium_src-72354315dd3c9682370ee2eea62446b7e5539990.tar.bz2
Avoid reporting crashes for exceptions that hit our SEH from calls to the original implementation of BindToStorage() when we do not wrap the bind status callback.
BUG=42660 TEST=Induce exception in code called under original IMoniker::BindToStorage implementation when we don't wrap the callback and notice that no crash is reported. Review URL: http://codereview.chromium.org/1748016 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@46176 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome_frame/chrome_frame_reporting.cc12
-rw-r--r--chrome_frame/crash_reporting/crash_report.cc39
-rw-r--r--chrome_frame/crash_reporting/vectored_handler-impl.h42
-rw-r--r--chrome_frame/exception_barrier.cc64
-rw-r--r--chrome_frame/exception_barrier.h234
-rw-r--r--chrome_frame/exception_barrier_lowlevel.asm8
-rw-r--r--chrome_frame/test/exception_barrier_unittest.cc35
-rw-r--r--chrome_frame/urlmon_moniker.cc9
8 files changed, 301 insertions, 142 deletions
diff --git a/chrome_frame/chrome_frame_reporting.cc b/chrome_frame/chrome_frame_reporting.cc
index 556747b2..807599c8 100644
--- a/chrome_frame/chrome_frame_reporting.cc
+++ b/chrome_frame/chrome_frame_reporting.cc
@@ -46,11 +46,6 @@ google_breakpad::CustomClientInfo* GetCustomInfo(const wchar_t* dll_path) {
return &custom_info;
}
-
-void CALLBACK BreakpadHandler(EXCEPTION_POINTERS *ptrs) {
- WriteMinidumpForException(ptrs);
-}
-
extern "C" IMAGE_DOS_HEADER __ImageBase;
bool InitializeCrashReporting() {
@@ -61,9 +56,9 @@ bool InitializeCrashReporting() {
if (!always_take_dump && !GoogleUpdateSettings::GetCollectStatsConsent())
return true;
- // Set the handler for ExceptionBarrier for this module:
- DCHECK(ExceptionBarrier::handler() == NULL);
- ExceptionBarrier::set_handler(BreakpadHandler);
+ // If we got here, we want to report crashes, so make sure all
+ // ExceptionBarrierBase instances do so.
+ ExceptionBarrierConfig::set_enabled(true);
// Get the alternate dump directory. We use the temp path.
FilePath temp_directory;
@@ -97,5 +92,6 @@ bool InitializeCrashReporting() {
}
bool ShutdownCrashReporting() {
+ ExceptionBarrierConfig::set_enabled(false);
return ShutdownVectoredCrashReporting();
}
diff --git a/chrome_frame/crash_reporting/crash_report.cc b/chrome_frame/crash_reporting/crash_report.cc
index cfb4e95..4589bab 100644
--- a/chrome_frame/crash_reporting/crash_report.cc
+++ b/chrome_frame/crash_reporting/crash_report.cc
@@ -47,36 +47,6 @@ static void veh_segment_end() {}
#pragma code_seg(push, ".text$vm")
#include "chrome_frame/crash_reporting/vectored_handler-impl.h"
-// Use Win32 API; use breakpad for dumps; checks for single (current) module.
-class CrashHandlerTraits : public Win32VEHTraits,
- public ModuleOfInterestWithExcludedRegion {
- public:
- CrashHandlerTraits() {}
-
- // Note that breakpad_lock must be held when this is called.
- void Init(google_breakpad::ExceptionHandler* breakpad, Lock* breakpad_lock) {
- DCHECK(breakpad);
- DCHECK(breakpad_lock);
- breakpad_lock->AssertAcquired();
-
- Win32VEHTraits::InitializeIgnoredBlocks();
- ModuleOfInterestWithExcludedRegion::SetCurrentModule();
- // Pointers to static (non-extern) functions take the address of the
- // function's first byte, as opposed to an entry in the compiler generated
- // JMP table. In release builds /OPT:REF wipes away the JMP table, but debug
- // builds are not so lucky.
- ModuleOfInterestWithExcludedRegion::SetExcludedRegion(&veh_segment_start,
- &veh_segment_end);
- }
-
- void Shutdown() {
- }
-
- inline bool WriteDump(EXCEPTION_POINTERS* p) {
- return WriteMinidumpForException(p);
- }
-};
-
class CrashHandler {
public:
CrashHandler() : veh_id_(NULL), handler_(&crash_api_) {}
@@ -115,14 +85,17 @@ bool CrashHandler::Init(google_breakpad::ExceptionHandler* breakpad,
if (veh_id_)
return true;
+ crash_api_.Init(&veh_segment_start, &veh_segment_end,
+ &WriteMinidumpForException);
+
void* id = ::AddVectoredExceptionHandler(FALSE, &VectoredHandlerEntryPoint);
if (id != NULL) {
veh_id_ = id;
- crash_api_.Init(breakpad, breakpad_lock);
return true;
+ } else {
+ crash_api_.Shutdown();
+ return false;
}
-
- return false;
}
void CrashHandler::Shutdown() {
diff --git a/chrome_frame/crash_reporting/vectored_handler-impl.h b/chrome_frame/crash_reporting/vectored_handler-impl.h
index 641522f..175e496 100644
--- a/chrome_frame/crash_reporting/vectored_handler-impl.h
+++ b/chrome_frame/crash_reporting/vectored_handler-impl.h
@@ -4,6 +4,8 @@
#ifndef CHROME_FRAME_CRASH_REPORTING_VECTORED_HANDLER_IMPL_H_
#define CHROME_FRAME_CRASH_REPORTING_VECTORED_HANDLER_IMPL_H_
+
+#include "base/logging.h"
#include "chrome_frame/crash_reporting/vectored_handler.h"
#include "chrome_frame/crash_reporting/nt_loader.h"
@@ -262,4 +264,44 @@ Win32VEHTraits::IgnoreExceptions[kIgnoreEntries] = {
{ "kernel32.dll", "IsBadStringPtrW", 0, 100, NULL },
};
+// Use Win32 API; checks for single (current) module. Will call a specified
+// CrashHandlerTraits::DumpHandler when taking a dump.
+class CrashHandlerTraits : public Win32VEHTraits,
+ public ModuleOfInterestWithExcludedRegion {
+ public:
+
+ typedef bool (*DumpHandler)(EXCEPTION_POINTERS* p);
+
+ CrashHandlerTraits() : dump_handler_(NULL) {}
+
+ // Note that breakpad_lock must be held when this is called.
+ void Init(const void* veh_segment_start, const void* veh_segment_end,
+ DumpHandler dump_handler) {
+ DCHECK(dump_handler);
+ dump_handler_ = dump_handler;
+ Win32VEHTraits::InitializeIgnoredBlocks();
+ ModuleOfInterestWithExcludedRegion::SetCurrentModule();
+ // Pointers to static (non-extern) functions take the address of the
+ // function's first byte, as opposed to an entry in the compiler generated
+ // JMP table. In release builds /OPT:REF wipes away the JMP table, but debug
+ // builds are not so lucky.
+ ModuleOfInterestWithExcludedRegion::SetExcludedRegion(veh_segment_start,
+ veh_segment_end);
+ }
+
+ void Shutdown() {
+ }
+
+ inline bool WriteDump(EXCEPTION_POINTERS* p) {
+ if (dump_handler_) {
+ return dump_handler_(p);
+ } else {
+ return false;
+ }
+ }
+
+ private:
+ DumpHandler dump_handler_;
+};
+
#endif // CHROME_FRAME_CRASH_REPORTING_VECTORED_HANDLER_IMPL_H_
diff --git a/chrome_frame/exception_barrier.cc b/chrome_frame/exception_barrier.cc
index 51e764a..6fb5480 100644
--- a/chrome_frame/exception_barrier.cc
+++ b/chrome_frame/exception_barrier.cc
@@ -6,12 +6,18 @@
// get crash reports of exceptions that pass over same.
#include "chrome_frame/exception_barrier.h"
+#include "chrome_frame/crash_reporting/vectored_handler-impl.h"
+#include "chrome_frame/crash_reporting/crash_report.h"
+
enum {
// Flag set by exception handling machinery when unwinding
EH_UNWINDING = 0x00000002
};
-ExceptionBarrier::ExceptionHandler ExceptionBarrier::s_handler_ = NULL;
+bool ExceptionBarrierConfig::s_enabled_ = false;
+
+ExceptionBarrierCustomHandler::CustomExceptionHandler
+ ExceptionBarrierCustomHandler::s_custom_handler_ = NULL;
// This function must be extern "C" to match up with the SAFESEH
// declaration in our corresponding ASM file
@@ -20,19 +26,53 @@ ExceptionBarrierHandler(struct _EXCEPTION_RECORD* exception_record,
void* establisher_frame,
struct _CONTEXT* context,
void* reserved) {
- establisher_frame; // unreferenced formal parameter
- reserved;
- if (!(exception_record->ExceptionFlags & EH_UNWINDING)) {
- // When the exception is really propagating through us, we'd like to be
- // called before the state of the program has been modified by the stack
- // unwinding. In the absence of an exception handler, the unhandled
- // exception filter gets called between the first chance and the second
- // chance exceptions, so Windows pops either the JIT debugger or WER UI.
- // This is not desirable in most of the cases.
- ExceptionBarrier::ExceptionHandler handler = ExceptionBarrier::handler();
+ // When the exception is really propagating through us, we'd like to be
+ // called before the state of the program has been modified by the stack
+ // unwinding. In the absence of an exception handler, the unhandled
+ // exception filter gets called between the first chance and the second
+ // chance exceptions, so Windows pops either the JIT debugger or WER UI.
+ // This is not desirable in most of the cases.
+ EXCEPTION_POINTERS ptrs = { exception_record, context };
+
+ if (ExceptionBarrierConfig::enabled() &&
+ IS_DISPATCHING(exception_record->ExceptionFlags)) {
+ WriteMinidumpForException(&ptrs);
+ }
+
+ return ExceptionContinueSearch;
+}
+
+extern "C" EXCEPTION_DISPOSITION __cdecl
+ExceptionBarrierReportOnlyModuleHandler(
+ struct _EXCEPTION_RECORD* exception_record,
+ void* establisher_frame,
+ struct _CONTEXT* context,
+ void* reserved) {
+ EXCEPTION_POINTERS ptrs = { exception_record, context };
+
+ if (ExceptionBarrierConfig::enabled() &&
+ IS_DISPATCHING(exception_record->ExceptionFlags)) {
+ CrashHandlerTraits traits;
+ traits.Init(0, 0, &WriteMinidumpForException);
+ if (traits.IsOurModule(exception_record->ExceptionAddress)) {
+ traits.WriteDump(&ptrs);
+ }
+ }
+
+ return ExceptionContinueSearch;
+}
+
+extern "C" EXCEPTION_DISPOSITION __cdecl
+ExceptionBarrierCallCustomHandler(struct _EXCEPTION_RECORD* exception_record,
+ void* establisher_frame,
+ struct _CONTEXT* context,
+ void* reserved) {
+ if (ExceptionBarrierConfig::enabled() &&
+ IS_DISPATCHING(exception_record->ExceptionFlags)) {
+ ExceptionBarrierCustomHandler::CustomExceptionHandler handler =
+ ExceptionBarrierCustomHandler::custom_handler();
if (handler) {
EXCEPTION_POINTERS ptrs = { exception_record, context };
-
handler(&ptrs);
}
}
diff --git a/chrome_frame/exception_barrier.h b/chrome_frame/exception_barrier.h
index 26cbc44..e3e5350 100644
--- a/chrome_frame/exception_barrier.h
+++ b/chrome_frame/exception_barrier.h
@@ -1,96 +1,196 @@
// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-
+//
// A class to make it easy to tag exception propagation boundaries and
// get crash reports of exceptions that pass over same.
+//
+// An exception barrier is used to report exceptions that pass through
+// a boundary where exceptions shouldn't pass, such as e.g. COM interface
+// boundaries.
+// This is handy for any kind of plugin code, where if the exception passes
+// through unhindered, it'll either be swallowed by an SEH exception handler
+// above us on the stack, or be reported as an unhandled exception for
+// the application hosting the plugin code.
+//
+// IMPORTANT NOTE: This class has crash_reporting disabled by default. To
+// enable crash reporting call:
+//
+// @code
+// ExceptionBarrierBase::set_crash_handling(true)
+// @endcode
+//
+// somewhere in your initialization code.
+//
+// Then, to use this class, simply instantiate an ExceptionBarrier just inside
+// the code boundary, like this:
+// @code
+// HRESULT SomeObject::SomeCOMMethod(...) {
+// ExceptionBarrier report_crashes;
+//
+// ... other code here ...
+// }
+// @endcode
+//
+// There are three ExceptionBarrier types defined here:
+// 1) ExceptionBarrier which reports all crashes it sees.
+// 2) ExceptionBarrierReportOnlyModule which reports only crashes occurring
+// in this module.
+// 3) ExceptionBarrierCustomHandler which calls the handler set by a call
+// to ExceptionBarrierCallCustomHandler::set_custom_handler(). Note that
+// there is one custom handler for all ExceptionBarrierCallCustomHandler
+// instances. If set_custom_handler() is never called, this places an
+// SEH in the chain that just returns ExceptionContinueSearch.
+
#ifndef CHROME_FRAME_EXCEPTION_BARRIER_H_
#define CHROME_FRAME_EXCEPTION_BARRIER_H_
#include <windows.h>
-/// This is the type dictated for an exception handler by the platform ABI
-/// @see _except_handler in excpt.h
-typedef EXCEPTION_DISPOSITION (__cdecl *ExceptionHandlerFunc)(
- struct _EXCEPTION_RECORD *exception_record,
- void * establisher_frame,
- struct _CONTEXT *context,
- void * reserved);
+extern "C" IMAGE_DOS_HEADER __ImageBase;
-/// The type of an exception record in the exception handler chain
+// This is the type dictated for an exception handler by the platform ABI
+// @see _except_handler in excpt.h
+typedef EXCEPTION_DISPOSITION (__cdecl* ExceptionHandlerFunc)(
+ struct _EXCEPTION_RECORD* exception_record,
+ void* establisher_frame,
+ struct _CONTEXT* context,
+ void* reserved);
+
+// The type of an exception record in the exception handler chain
struct EXCEPTION_REGISTRATION {
- EXCEPTION_REGISTRATION *prev;
+ EXCEPTION_REGISTRATION* prev;
ExceptionHandlerFunc handler;
};
-/// This is our raw exception handler, it must be declared extern "C" to
-/// match up with the SAFESEH declaration in our corresponding ASM file
+// This is our raw exception handler, it must be declared extern "C" to
+// match up with the SAFESEH declaration in our corresponding ASM file.
+extern "C" EXCEPTION_DISPOSITION __cdecl
+ExceptionBarrierHandler(struct _EXCEPTION_RECORD* exception_record,
+ void* establisher_frame,
+ struct _CONTEXT* context,
+ void* reserved);
+
+// An alternate raw exception handler that reports crashes only for the current
+// module. It must be declared extern "C" to match up with the SAFESEH
+// declaration in our corresponding ASM file.
extern "C" EXCEPTION_DISPOSITION __cdecl
-ExceptionBarrierHandler(struct _EXCEPTION_RECORD *exception_record,
- void * establisher_frame,
- struct _CONTEXT *context,
- void * reserved);
-
-/// An exception barrier is used to report exceptions that pass through
-/// a boundary where exceptions shouldn't pass, such as e.g. COM interface
-/// boundaries.
-/// This is handy for any kind of plugin code, where if the exception passes
-/// through unhindered, it'll either be swallowed by an SEH exception handler
-/// above us on the stack, or be reported as an unhandled exception for
-/// the application hosting the plugin code.
-///
-/// To use this class, simply instantiate an ExceptionBarrier just inside
-/// the code boundary, like this:
-/// @code
-/// HRESULT SomeObject::SomeCOMMethod(...) {
-/// ExceptionBarrier report_crashes;
-///
-/// ... other code here ...
-/// }
-/// @endcode
-class ExceptionBarrier {
+ExceptionBarrierReportOnlyModuleHandler(
+ struct _EXCEPTION_RECORD* exception_record,
+ void* establisher_frame,
+ struct _CONTEXT* context,
+ void* reserved);
+
+// An alternate raw exception handler that calls out to a custom handler.
+// It must be declared extern "C" to match up with the SAFESEH declaration in
+// our corresponding ASM file.
+extern "C" EXCEPTION_DISPOSITION __cdecl
+ExceptionBarrierCallCustomHandler(
+ struct _EXCEPTION_RECORD* exception_record,
+ void* establisher_frame,
+ struct _CONTEXT* context,
+ void* reserved);
+
+
+// @name These are implemented in the associated .asm file
+// @{
+extern "C" void WINAPI RegisterExceptionRecord(
+ EXCEPTION_REGISTRATION* registration,
+ ExceptionHandlerFunc func);
+extern "C" void WINAPI UnregisterExceptionRecord(
+ EXCEPTION_REGISTRATION* registration);
+// @}
+
+
+// Traits classes for ExceptionBarrierT.
+class EBTraitsBase {
public:
- /// Register the barrier in the SEH chain
- ExceptionBarrier();
+ static void UnregisterException(EXCEPTION_REGISTRATION* registration) {
+ UnregisterExceptionRecord(registration);
+ }
+};
- /// And unregister on destruction
- ~ExceptionBarrier();
+class EBReportAllTraits : public EBTraitsBase {
+ public:
+ static void RegisterException(EXCEPTION_REGISTRATION* registration) {
+ RegisterExceptionRecord(registration, ExceptionBarrierHandler);
+ }
+};
- /// Signature of the handler function which gets notified when
- /// an exception propagates through a barrier.
- typedef void (CALLBACK *ExceptionHandler)(EXCEPTION_POINTERS *ptrs);
+class EBReportOnlyThisModuleTraits : public EBTraitsBase {
+ public:
+ static void RegisterException(EXCEPTION_REGISTRATION* registration) {
+ RegisterExceptionRecord(registration,
+ ExceptionBarrierReportOnlyModuleHandler);
+ }
+};
- /// @name Accessors
- /// @{
- static void set_handler(ExceptionHandler handler) { s_handler_ = handler; }
- static ExceptionHandler handler() { return s_handler_; }
- /// @}
+class EBCustomHandlerTraits : public EBTraitsBase {
+ public:
+ static void RegisterException(EXCEPTION_REGISTRATION* registration) {
+ RegisterExceptionRecord(registration,
+ ExceptionBarrierCallCustomHandler);
+ }
+};
- private:
- /// Our SEH frame
- EXCEPTION_REGISTRATION registration_;
+class ExceptionBarrierConfig {
+ public:
+ // Used to globally enable or disable crash handling by ExceptionBarrierBase
+ // instances.
+ static void set_enabled(bool enabled) {
+ s_enabled_ = enabled;
+ }
+ static bool enabled() { return s_enabled_; }
+
+ // Whether crash reports are enabled.
+ static bool s_enabled_;
+};
- /// The function that gets invoked if an exception
- /// propagates through a barrier
- static ExceptionHandler s_handler_;
+template <typename RegistrarTraits>
+class ExceptionBarrierT {
+ public:
+ // Register the barrier in the SEH chain
+ ExceptionBarrierT() {
+ RegistrarTraits::RegisterException(&registration_);
+ }
+
+ // Unregister on destruction
+ virtual ~ExceptionBarrierT() {
+ RegistrarTraits::UnregisterException(&registration_);
+ }
+
+ protected:
+ // Our SEH frame
+ EXCEPTION_REGISTRATION registration_;
};
-/// @name These are implemented in the associated .asm file
-/// @{
-extern "C" void WINAPI RegisterExceptionRecord(
- EXCEPTION_REGISTRATION *registration,
- ExceptionHandlerFunc func);
-extern "C" void WINAPI UnregisterExceptionRecord(
- EXCEPTION_REGISTRATION *registration);
-/// @}
+// This class allows for setting a custom exception handler function. The
+// handler is shared among all instances. This class is intended to enable
+// testing of the SEH registration.
+template <typename RegistrarTraits>
+class ExceptionBarrierCustomHandlerT :
+ public ExceptionBarrierT<typename RegistrarTraits> {
+ public:
+ // Signature of the handler function which gets notified when
+ // an exception propagates through a barrier.
+ typedef void (CALLBACK* CustomExceptionHandler)(EXCEPTION_POINTERS* ptrs);
+ // Used to set a global custom handler used by all
+ // ExceptionBarrierCustomHandler instances.
+ static void set_custom_handler(CustomExceptionHandler handler) {
+ s_custom_handler_ = handler;
+ }
+ static CustomExceptionHandler custom_handler() { return s_custom_handler_; }
-inline ExceptionBarrier::ExceptionBarrier() {
- RegisterExceptionRecord(&registration_, ExceptionBarrierHandler);
-}
+ private:
+ static CustomExceptionHandler s_custom_handler_;
+};
-inline ExceptionBarrier::~ExceptionBarrier() {
- UnregisterExceptionRecord(&registration_);
-}
+// Convenience typedefs for the ExceptionBarrierT specializations.
+typedef ExceptionBarrierT<EBReportAllTraits> ExceptionBarrier;
+typedef ExceptionBarrierT<EBReportOnlyThisModuleTraits>
+ ExceptionBarrierReportOnlyModule;
+typedef ExceptionBarrierCustomHandlerT<EBCustomHandlerTraits>
+ ExceptionBarrierCustomHandler;
#endif // CHROME_FRAME_EXCEPTION_BARRIER_H_
diff --git a/chrome_frame/exception_barrier_lowlevel.asm b/chrome_frame/exception_barrier_lowlevel.asm
index b759990..f8f652f 100644
--- a/chrome_frame/exception_barrier_lowlevel.asm
+++ b/chrome_frame/exception_barrier_lowlevel.asm
@@ -10,9 +10,17 @@
IF @version LT 800
_ExceptionBarrierHandler PROTO
.SAFESEH _ExceptionBarrierHandler
+_ExceptionBarrierReportOnlyModuleHandler PROTO
+.SAFESEH _ExceptionBarrierReportOnlyModuleHandler
+_ExceptionBarrierCallCustomHandler PROTO
+.SAFESEH _ExceptionBarrierCallCustomHandler
ELSE
ExceptionBarrierHandler PROTO
.SAFESEH ExceptionBarrierHandler
+ExceptionBarrierReportOnlyModuleHandler PROTO
+.SAFESEH ExceptionBarrierReportOnlyModuleHandler
+ExceptionBarrierCallCustomHandler PROTO
+.SAFESEH ExceptionBarrierCallCustomHandler
ENDIF
.586
diff --git a/chrome_frame/test/exception_barrier_unittest.cc b/chrome_frame/test/exception_barrier_unittest.cc
index c31d878..eeffd2a 100644
--- a/chrome_frame/test/exception_barrier_unittest.cc
+++ b/chrome_frame/test/exception_barrier_unittest.cc
@@ -75,7 +75,7 @@ void AccessViolationCrash() {
// A simple crash over the exception barrier
void CrashOverExceptionBarrier() {
- ExceptionBarrier barrier;
+ ExceptionBarrierCustomHandler barrier;
TestSEHChainSane();
@@ -85,15 +85,15 @@ void CrashOverExceptionBarrier() {
}
#pragma warning(push)
- // Inline asm assigning to 'FS:0' : handler not registered as safe handler
- // This warning is in error (the compiler can't know that we register the
- // handler as a safe SEH handler in an .asm file)
- #pragma warning(disable:4733)
-// Hand-generate an SEH frame implicating the ExceptionBarrierHandler,
+// Inline asm assigning to 'FS:0' : handler not registered as safe handler
+// This warning is in error (the compiler can't know that we register the
+// handler as a safe SEH handler in an .asm file)
+#pragma warning(disable:4733)
+// Hand-generate an SEH frame implicating the ExceptionBarrierCallCustomHandler,
// then crash to invoke it.
__declspec(naked) void CrashOnManualSEHBarrierHandler() {
__asm {
- push ExceptionBarrierHandler
+ push ExceptionBarrierCallCustomHandler
push FS:0
mov FS:0, esp
call AccessViolationCrash
@@ -102,43 +102,40 @@ __declspec(naked) void CrashOnManualSEHBarrierHandler() {
}
#pragma warning(pop)
+
class ExceptionBarrierTest: public testing::Test {
-public:
- ExceptionBarrierTest() : old_handler_(NULL) {
+ public:
+ ExceptionBarrierTest() {
}
// Install an exception handler for the ExceptionBarrier, and
// set the handled flag to false. This allows us to see whether
// the ExceptionBarrier gets to handle the exception
virtual void SetUp() {
- old_handler_ = ExceptionBarrier::handler();
- ExceptionBarrier::set_handler(ExceptionHandler);
+ ExceptionBarrierConfig::set_enabled(true);
+ ExceptionBarrierCustomHandler::set_custom_handler(&ExceptionHandler);
s_handled_ = false;
TestSEHChainSane();
}
virtual void TearDown() {
- ExceptionBarrier::set_handler(old_handler_);
-
TestSEHChainSane();
+ ExceptionBarrierCustomHandler::set_custom_handler(NULL);
+ ExceptionBarrierConfig::set_enabled(false);
}
// The exception notification callback, sets the handled flag.
static void CALLBACK ExceptionHandler(EXCEPTION_POINTERS* ptrs) {
TestSEHChainSane();
-
s_handled_ = true;
}
- // Old handler to restore on TearDown
- ExceptionBarrier::ExceptionHandler old_handler_;
-
// Flag is set by handler
static bool s_handled_;
};
-bool ExceptionBarrierTest::s_handled_;
+bool ExceptionBarrierTest::s_handled_ = false;
bool TestExceptionExceptionBarrierHandler() {
TestSEHChainSane();
@@ -271,7 +268,7 @@ bool TestRegularChaining(EXCEPTION_REGISTRATION* top) {
}
void RecurseAndCrashOverBarrier(int depth, bool crash) {
- ExceptionBarrier barrier;
+ ExceptionBarrierCustomHandler barrier;
if (0 == depth) {
if (crash)
diff --git a/chrome_frame/urlmon_moniker.cc b/chrome_frame/urlmon_moniker.cc
index 4150927..cc9d6a8 100644
--- a/chrome_frame/urlmon_moniker.cc
+++ b/chrome_frame/urlmon_moniker.cc
@@ -174,7 +174,7 @@ HRESULT MonikerPatch::BindToObject(IMoniker_BindToObject_Fn original,
DLOG(INFO) << __FUNCTION__;
DCHECK(to_left == NULL);
- ExceptionBarrier barrier;
+ ExceptionBarrierReportOnlyModule barrier;
HRESULT hr = S_OK;
// Bind context is marked for switch when we sniff data in BSCBStorageBind
@@ -217,11 +217,14 @@ HRESULT MonikerPatch::BindToStorage(IMoniker_BindToStorage_Fn original,
hr = callback->Initialize(me, bind_ctx);
DCHECK(SUCCEEDED(hr));
- // Call the original back under an exception barrier only if we should
- // wrap the callback.
+ // Report all crashes in the exception handler if we wrap the callback.
+ // Note that this avoids having the VEH report a crash if an SEH earlier in
+ // the chain handles the exception.
ExceptionBarrier barrier;
hr = original(me, bind_ctx, to_left, iid, obj);
} else {
+ // If we don't wrap, only report a crash if the crash is in our own module.
+ ExceptionBarrierReportOnlyModule barrier;
hr = original(me, bind_ctx, to_left, iid, obj);
}