add_definitions(-DFEATURE_BASICFREEZE)
add_definitions(-DFEATURE_CORECLR)
add_definitions(-DFEATURE_CORESYSTEM)
-add_definitions(-DFEATURE_CORRUPTING_EXCEPTIONS)
if(FEATURE_DBGIPC)
add_definitions(-DFEATURE_DBGIPC_TRANSPORT_DI)
add_definitions(-DFEATURE_DBGIPC_TRANSPORT_VM)
CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_AssertOnFailFast, W("AssertOnFailFast"), "")
RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_legacyCorruptedStateExceptionsPolicy, W("legacyCorruptedStateExceptionsPolicy"), 0, "Enabled Pre-V4 CSE behavior", CLRConfig::EEConfig_default)
CONFIG_DWORD_INFO_EX(INTERNAL_SuppressLostExceptionTypeAssert, W("SuppressLostExceptionTypeAssert"), 0, "", CLRConfig::EEConfig_default)
-RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_FailFastOnCorruptedStateException, W("FailFastOnCorruptedStateException"), 0, "Failfast if a CSE is encountered", CLRConfig::EEConfig_default)
RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_UseEntryPointFilter, W("UseEntryPointFilter"), 0, "", CLRConfig::EEConfig_default)
RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_Corhost_Swallow_Uncaught_Exceptions, W("Corhost_Swallow_Uncaught_Exceptions"), 0, "", CLRConfig::EEConfig_default)
interface IAssemblyName;
-// PE images loaded through the runtime.
-typedef struct _dummyCOR { BYTE b; } *HCORMODULE;
-
class UTSemReadWrite;
// Helper function to get a pointer to the Dispenser interface.
REFIID riid, // [IN] The interface desired.
IUnknown **ppIUnk); // [OUT] Return interface on success.
-HRESULT GetAssemblyMDInternalImportFromImage(
- HCORMODULE hImage, //[IN] pointer to module handle to get the metadata from.
- REFIID riid, //[IN] The interface desired.
- IUnknown **ppIUnk); //[OUT] Return Interface on success.
-
STDAPI GetAssemblyMDInternalImportByStream( // Return code.
IStream *pIStream, // [IN] The IStream for the file
UINT64 AssemblyId, // [IN] Unique Id for the assembly
#define COR_MODULE_CLASS "<Module>"
#define COR_WMODULE_CLASS W("<Module>")
-STDAPI RuntimeOpenImage(LPCWSTR pszFileName, HCORMODULE* hHandle);
-STDAPI RuntimeOpenImageInternal(LPCWSTR pszFileName, HCORMODULE* hHandle,
- DWORD *pdwLength, MDInternalImportFlags flags, HANDLE hFile = INVALID_HANDLE_VALUE);
-STDAPI RuntimeOpenImageByStream(IStream* pIStream, UINT64 AssemblyId, DWORD dwModuleId,
- HCORMODULE* hHandle, DWORD *pdwLength, MDInternalImportFlags flags);
-
-void RuntimeAddRefHandle(HCORMODULE hHandle);
-STDAPI RuntimeReleaseHandle(HCORMODULE hHandle);
-STDAPI RuntimeGetImageBase(HCORMODULE hHandle, LPVOID* base, BOOL bMapped, COUNT_T* dwSize);
-STDAPI RuntimeGetImageKind(HCORMODULE hHandle, DWORD* pdwKind, DWORD* pdwMachine);
-STDAPI RuntimeOSHandle(HCORMODULE hHandle, HMODULE* hModule);
-STDAPI RuntimeGetAssemblyStrongNameHashForModule(HCORMODULE hModule,
- IMetaDataImport *pMDimport,
- BYTE *pbSNHash,
- DWORD *pcbSNHash);
-STDAPI RuntimeGetMDInternalImport(HCORMODULE hHandle,
- MDInternalImportFlags flags,
- IMDInternalImport** ppMDImport);
-
-FORCEINLINE
-void ReleaseHCorModule(HCORMODULE hModule)
-{
- HRESULT hr = RuntimeReleaseHandle(hModule);
- _ASSERTE(SUCCEEDED(hr));
-}
-
-typedef Wrapper<HCORMODULE, DoNothing<HCORMODULE>, ReleaseHCorModule, (UINT_PTR) NULL> HCORMODULEHolder;
-
-
-// ===========================================================================
-// ISNAssemblySignature (similar to IAssemblySignature in V1)
-//
-// This is a private interface that allows querying of the strong name
-// signature.
-// This can be used for (strong-named) assemblies added to the GAC as
-// a unique identifier.
-//
-
-// {848845BC-0C4A-42e3-8915-DC850112443D}
-EXTERN_GUID(IID_ISNAssemblySignature, 0x848845BC, 0x0C4A, 0x42e3, 0x89, 0x15, 0xDC, 0x85, 0x01, 0x12, 0x44, 0x3D);
-
-#undef INTERFACE
-#define INTERFACE ISNAssemblySignature
-DECLARE_INTERFACE_(ISNAssemblySignature, IUnknown)
-{
- // Returns the strong-name signature if the assembly is strong-name-signed
- // Returns the MVID if the assembly is delay-signed.
- // Fails if the assembly is not signed at all.
- STDMETHOD(GetSNAssemblySignature) (
- BYTE *pbSig, // [IN, OUT] Buffer to write signature
- DWORD *pcbSig // [IN, OUT] Size of buffer, bytes written
- ) PURE;
-};
-
//-------------------------------------
//--- ICeeGenInternal
//-------------------------------------
EX_RETHROW; \
} \
-// Don't use this - use RethrowCorruptingExceptions (see below) instead.
#define SwallowAllExceptions ;
-//////////////////////////////////////////////////////////////////////
-//
-// Corrupted State Exception Support
-//
-/////////////////////////////////////////////////////////////////////
-
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
-
-#define CORRUPTING_EXCEPTIONS_ONLY(expr) expr
-#define COMMA_CORRUPTING_EXCEPTIONS_ONLY(expr) ,expr
-
-// EX_END_CATCH has been modified to not swallow Corrupting Exceptions (CE) when one of the
-// following arguments are passed to it:
-//
-// 1) RethrowTerminalExceptions - rethrows both terminal and corrupting exceptions
-// 2) RethrowCorruptingExceptions - swallows all exceptions exception corrupting exceptions. This SHOULD BE USED instead of SwallowAllExceptions.
-// 3) RethrowTerminalExceptionsEx - same as (1) but rethrow of CE can be controlled via a condition.
-// 4) RethrowCorruptingExceptionsEx - same as (2) but rethrow of CE can be controlled via a condition.
-//
-// By default, if a CE is encountered when one of the above policies are applied, the runtime will
-// ensure that the CE propagates up the stack and not get swallowed unless the developer chooses to override the behaviour.
-// This can be done by using the "Ex" versions above that take a conditional which evaluates to a BOOL. In such a case,
-// the CE will *only* be rethrown if the conditional evalutes to TRUE. For examples, refer to COMToCLRWorker or
-// DispatchInfo::InvokeMember implementations.
-//
-// SET_CE_RETHROW_FLAG_FOR_EX_CATCH macros helps evaluate if the CE is to be rethrown or not. This has been redefined in
-// Clrex.h to add the condition of evaluating the throwable as well (which is not available outside the VM folder).
-//
-// Passing FALSE as the second argument to IsProcessCorruptedStateException implies that SET_CE_RETHROW_FLAG_FOR_EX_CATCH
-// will ensure that we dont rethrow SO and allow EX_ENDTRY to SO specific processing. If none is done, then EX_ENDTRY will
-// rethrow SO. By that time stack has been reclaimed and thus, throwing SO will be safe.
-//
-// We also check the global override flag incase it has been set to force pre-V4 beahviour. "0" implies it has not
-// been overriden.
-#define SET_CE_RETHROW_FLAG_FOR_EX_CATCH(expr) ((((expr) == TRUE) && \
- (CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_legacyCorruptedStateExceptionsPolicy) == 0) && \
- IsProcessCorruptedStateException(GetCurrentExceptionCode(), FALSE)))
-
-// This rethrow policy can be used in EX_END_CATCH to swallow all exceptions except the corrupting ones.
-// This macro can be used to rethrow the CE based upon a BOOL condition.
-#define RethrowCorruptingExceptionsEx(expr) \
- if (SET_CE_RETHROW_FLAG_FOR_EX_CATCH(expr)) \
- { \
- STATIC_CONTRACT_THROWS_TERMINAL; \
- EX_RETHROW; \
- }
-
-#define RethrowCorruptingExceptionsExAndHookRethrow(shouldRethrowExpr, aboutToRethrowExpr) \
- if (SET_CE_RETHROW_FLAG_FOR_EX_CATCH(shouldRethrowExpr)) \
- { \
- STATIC_CONTRACT_THROWS_TERMINAL; \
- aboutToRethrowExpr; \
- EX_RETHROW; \
- }
-
-#else // !FEATURE_CORRUPTING_EXCEPTIONS
-
-#define CORRUPTING_EXCEPTIONS_ONLY(expr)
-#define COMMA_CORRUPTING_EXCEPTIONS_ONLY(expr)
-
-// When we dont have support for CE, just map it to SwallowAllExceptions
-#define RethrowCorruptingExceptionsEx(expr) SwallowAllExceptions
-#define RethrowCorruptingExceptionsExAndHookRethrow(shouldRethrowExpr, aboutToRethrowExpr) SwallowAllExceptions
-#define SET_CE_RETHROW_FLAG_FOR_EX_CATCH(expr) !TRUE
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
-
-// Map to RethrowCorruptingExceptionsEx so that it does the "right" thing
-#define RethrowCorruptingExceptions RethrowCorruptingExceptionsEx(TRUE)
-
-// This macro can be used to rethrow the CE based upon a BOOL condition. It will continue to rethrow terminal
-// exceptions unconditionally.
-#define RethrowTerminalExceptionsEx(expr) \
- if (GET_EXCEPTION()->IsTerminal() || \
- SET_CE_RETHROW_FLAG_FOR_EX_CATCH(expr)) \
+// When applied to EX_END_CATCH, this policy will always rethrow Terminal exceptions if they are
+// encountered.
+#define RethrowTerminalExceptions \
+ if (GET_EXCEPTION()->IsTerminal()) \
{ \
STATIC_CONTRACT_THROWS_TERMINAL; \
EX_RETHROW; \
} \
-
-// When applied to EX_END_CATCH, this policy will always rethrow Terminal and Corrupting exceptions if they are
-// encountered.
-#define RethrowTerminalExceptions RethrowTerminalExceptionsEx(TRUE)
-
// Special define to be used in EEStartup that will also check for VM initialization before
// commencing on a path that may use the managed thread object.
#define RethrowTerminalExceptionsWithInitCheck \
extern HINSTANCE g_hmodCoreCLR;
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
-
-// Corrupting Exception limited support for outside the VM folder
-BOOL IsProcessCorruptedStateException(DWORD dwExceptionCode, BOOL fCheckForSO = TRUE);
-
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
-
namespace UtilCode
{
// These are type-safe versions of Interlocked[Compare]Exchange
#include "mdinternalro.h"
-
enum MDFileFormat
{
MDFormat_ReadOnly = 0,
MDFormat_Invalid = 3
};
-
-HRESULT CheckFileFormat(LPVOID pData, ULONG cbData, MDFileFormat *pFormat);
STDAPI GetMDInternalInterface(
LPVOID pData, // [IN] Buffer with the metadata.
ULONG cbData, // [IN] Size of the data in the buffer.
REFIID riid, // [in] The interface desired.
void **ppIUnk); // [out] Return interface on success.
-HRESULT GetAssemblyMDInternalImportHelper(HCORMODULE hModule,
- REFIID riid,
- MDInternalImportFlags flags,
- IUnknown **ppIUnk);
-
#endif //FEATURE_METADATA_INTERNAL_APIS
#endif // __MDInternalDispenser__h__
return param.fRet;
}
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
-
-// To include definition of EXCEPTION_SOFTSO
-#include "corexcep.h"
-
-// These functions provide limited support for corrupting exceptions
-// outside the VM folder. Its limited since we don't have access to the
-// throwable.
-//
-// These functions are also wrapped by the corresponding CEHelper
-// methods in excep.cpp.
-
-// Given an exception code, this method returns a BOOL to indicate if the
-// code belongs to a corrupting exception or not.
-BOOL IsProcessCorruptedStateException(DWORD dwExceptionCode, BOOL fCheckForSO /*=TRUE*/)
-{
- LIMITED_METHOD_CONTRACT;
-
- // By default, assume its not corrupting
- BOOL fIsCorruptedStateException = FALSE;
-
- if (CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_legacyCorruptedStateExceptionsPolicy) == 1)
- {
- return fIsCorruptedStateException;
- }
-
- // If we have been asked not to include SO in the CSE check
- // and the code represent SO, then exit now.
- if ((fCheckForSO == FALSE) && (dwExceptionCode == STATUS_STACK_OVERFLOW))
- {
- return fIsCorruptedStateException;
- }
-
- switch(dwExceptionCode)
- {
- case STATUS_ACCESS_VIOLATION:
- case STATUS_STACK_OVERFLOW:
- case EXCEPTION_ILLEGAL_INSTRUCTION:
- case EXCEPTION_IN_PAGE_ERROR:
- case EXCEPTION_INVALID_DISPOSITION:
- case EXCEPTION_NONCONTINUABLE_EXCEPTION:
- case EXCEPTION_PRIV_INSTRUCTION:
- case STATUS_UNWIND_CONSOLIDATE:
- fIsCorruptedStateException = TRUE;
- break;
- }
-
- return fIsCorruptedStateException;
-}
-
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
-
namespace Clr
{
namespace Util
"FEATURE_COMINTEROP_WINRT_MANAGED_ACTIVATION",
"FEATURE_CORECLR",
"FEATURE_CORESYSTEM",
- "FEATURE_CORRUPTING_EXCEPTIONS",
"FEATURE_DATABREAKPOINT",
"FEATURE_DEFAULT_INTERFACES",
"FEATURE_EVENT_TRACE=1",
EX_CATCH
{
}
- EX_END_CATCH(RethrowCorruptingExceptions)
+ EX_END_CATCH(RethrowTerminalExceptions)
if (!table)
{
EX_CATCH
{
}
- EX_END_CATCH(RethrowCorruptingExceptions)
+ EX_END_CATCH(RethrowTerminalExceptions)
if (!table)
{
// {
// EX_RETHROW()
// }
-// EX_END_CATCH(RethrowTerminalExceptions or RethrowCorruptingExceptions)
+// EX_END_CATCH(RethrowTerminalExceptions)
// --------------------------------------------------------------------------------------------------------
// In DAC builds, we don't want to override the normal utilcode exception handling.
#define GET_THROWABLE() CLRException::GetThrowableFromException(GET_EXCEPTION())
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
-
-// For the VM folder, we redefine SET_CE_RETHROW_FLAG_FOR_EX_CATCH to also check the
-// corruption severity when deciding whether to rethrow them or not.
-//
-// We also check the global override flag incase it has been set to force pre-V4 behaviour.
-//
-// Doing the checks for "__fCaughtSO" and "__fCaughtNonCxx" will ensure that we check for
-// corruption severity only if the last exception was a managed exception that could have been rethrown in the VM.
-// When "(__fCaughtSO == FALSE) && (__fCaughtNonCxx == true)" is true, it implies we are dealing with a managed exception
-// inside the VM that is represented by the CLRLastThrownObjectException instance (see EX_TRY/EX_CATCH implementation in VM
-// folder to see how CLRLastThrownObjectException is used).
-//
-// This macro also supports the following scenarios:
-//
-// Scenario 1
-// ----------
-//
-// [VM1] -> [VM2] -> <managed code>
-//
-// If a managed exception is swallowed by an EX_CATCH in native function VM2, which then returns back
-// to native function VM1 that throws, for example, a VM C++ exception, an EX_CATCH(RethrowCorruptingExceptions)
-// in VM1 that catches the C++ exception will not rethrow since the last exception was not a managed CSE but
-// a C++ exception.
-//
-// A variation of this is for VM2 to return back in VM1, which calls VM3 that throws a VM C++ exception that
-// reaches VM1's EX_CATCH(RethrowCorruptingExceptions). VM1 shouldn't be rethrowing the exception in such a case.
-//
-// Scenario 2
-// ----------
-//
-// [VM1 - RethrowCSE] -> [VM2 - RethrowCSE] -> [VM3 - RethrowCSE] -> <managed code>
-//
-// When managed code throws a CSE (e.g. TargetInvocationException flagged as CSE), [VM3] will rethrow it and we will
-// enter EX_CATCH in VM2 which is supposed to rethrow it as well. But if the implementation of EX_CATCH in VM2 throws
-// another VM C++ exception (e.g. EEFileLoadException) *before* rethrow policy is applied, control will reach EX_CATCH
-// in VM1 that *shouldn't* rethrow (even though it has RethrowCSE as the policy) since the last exception was a VM C++
-// exception.
-//
-// Scenario 3
-// ----------
-//
-// This is about VM throwing a managed exception that gets handled either within the VM, with or without CLR's managed code
-// exception handler coming into the picture.
-//
-// This is explained in detail (alongwith relevant changes) in the implementation of RaiseTheException (in excep.cpp).
-
-#undef SET_CE_RETHROW_FLAG_FOR_EX_CATCH
-#define SET_CE_RETHROW_FLAG_FOR_EX_CATCH(expr) (((expr) == TRUE) && \
- (g_pConfig->LegacyCorruptedStateExceptionsPolicy() == false) && \
- (CEHelper::IsProcessCorruptedStateException(GetCurrentExceptionCode(), FALSE) || \
- (!__state.DidCatchCxx() && \
- CEHelper::IsLastActiveExceptionCorrupting(TRUE))))
-
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
-
#undef EX_TRY
#define EX_TRY \
EX_TRY_CUSTOM(CLRException::HandlerState, (::GetThreadNULLOk()), CLRLastThrownObjectException)
} \
} \
-// This macro should be used at the entry points (e.g. COM interop boundaries)
-// where CE's are not expected to get swallowed.
-#define END_EXTERNAL_ENTRYPOINT_RETHROW_CORRUPTING_EXCEPTIONS_EX(fCond) \
- } \
- EX_CATCH \
- { \
- *__phr = GET_EXCEPTION()->GetHR(); \
- } \
- EX_END_CATCH(RethrowCorruptingExceptionsEx(fCond)); \
- } \
- } \
-
-// This macro should be used at the entry points (e.g. COM interop boundaries)
-// where CE's are not expected to get swallowed.
-#define END_EXTERNAL_ENTRYPOINT_RETHROW_CORRUPTING_EXCEPTIONS \
- END_EXTERNAL_ENTRYPOINT_RETHROW_CORRUPTING_EXCEPTIONS_EX(TRUE)
-
-
-
//==============================================================================
// ---------------------------------------------------------------------------
CorIfaceAttr ifaceType = hndDefItfClass.GetMethodTable()->GetComInterfaceType();
if (IsDispatchBasedItf(ifaceType))
{
- RETURN (IDispatch*)GetComIPFromCCW(this, GUID_NULL, hndDefItfClass.GetMethodTable(),
- GetComIPFromCCW::SuppressSecurityCheck);
+ RETURN (IDispatch*)GetComIPFromCCW(this, GUID_NULL, hndDefItfClass.GetMethodTable());
}
else
{
{
None = 0,
CheckVisibility = 1,
- SuppressSecurityCheck = 2,
- SuppressCustomizedQueryInterface = 4
+ SuppressCustomizedQueryInterface = 2
};
};
EX_TRY
{
-#if defined(FEATURE_CORRUPTING_EXCEPTIONS)
- BOOL fCanMethodHandleException = g_pConfig->LegacyCorruptedStateExceptionsPolicy();
- if (!fCanMethodHandleException)
- {
- // CSE policy has not been overridden - proceed with our checks.
- //
- // Notifications for CSE are only delivered if the delegate target follows CSE rules.
- // So, get the corruption severity of the active exception that has gone unhandled.
- //
- // By Default, assume that the active exception is not corrupting.
- CorruptionSeverity severity = NotCorrupting;
- Thread *pCurThread = GetThread();
- _ASSERTE(pCurThread != NULL);
- ThreadExceptionState *pExState = pCurThread->GetExceptionState();
- if (pExState->IsExceptionInProgress())
- {
- // If an exception is active, it implies we have a tracker for it.
- // Hence, get the corruption severity from the active exception tracker.
- severity = pExState->GetCurrentExceptionTracker()->GetCorruptionSeverity();
- _ASSERTE(severity > NotSet);
- }
-
- // Notifications are delivered based upon corruption severity of the exception
- fCanMethodHandleException = ExceptionNotifications::CanDelegateBeInvokedForException(pDelegate, severity);
- if (!fCanMethodHandleException)
- {
- LOG((LF_EH, LL_INFO100, "InvokeUnhandledSwallowing: ADUEN Delegate cannot be invoked for corruption severity %d\n",
- severity));
- }
- }
-
- if (fCanMethodHandleException)
-#endif // defined(FEATURE_CORRUPTING_EXCEPTIONS)
- {
- // We've already exercised the prestub on this delegate's COMDelegate::GetMethodDesc,
- // as part of wiring up a reliable event sink. Deliver the notification.
- ExceptionNotifications::DeliverExceptionNotification(UnhandledExceptionHandler, pDelegate, pDomain, pEventArgs);
- }
+ ExceptionNotifications::DeliverExceptionNotification(UnhandledExceptionHandler, pDelegate, pDomain, pEventArgs);
}
EX_CATCH
{
BEGIN_QCALL;
- // This returns the base address - this will work for either HMODULE or HCORMODULES
+ // This returns the base address
// Other modules should have zero base
PEFile *pPEFile = pModule->GetFile();
if (!pPEFile->IsDynamic() && !pPEFile->IsResource())
}
FCIMPLEND
-
EX_CATCH
{
pThrowable = GET_THROWABLE();
-
- // RethrowCorruptingExceptionsEx, in EX_END_CATCH below, will ensure that CEs are rethrown.
}
- EX_END_CATCH(RethrowCorruptingExceptionsEx(!CEHelper::CanIDispatchTargetHandleException()))
+ EX_END_CATCH(RethrowTerminalExceptions)
catchFrame.Pop();
if (pThrowable != NULL)
fJitMinOpts = false;
fPInvokeRestoreEsp = (DWORD)-1;
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- // By default, there is not pre-V4 CSE policy
- fLegacyCorruptedStateExceptionsPolicy = false;
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
-
fNgenBindOptimizeNonGac = false;
fStressLog = false;
fProbeForStackOverflow = true;
}
}
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- // Returns a bool to indicate if the legacy CSE (pre-v4) behaviour is enabled or not
- bool LegacyCorruptedStateExceptionsPolicy(void) const {LIMITED_METHOD_CONTRACT; return fLegacyCorruptedStateExceptionsPolicy; }
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
-
bool InteropValidatePinnedObjects() const { LIMITED_METHOD_CONTRACT; return m_fInteropValidatePinnedObjects; }
bool InteropLogArguments() const { LIMITED_METHOD_CONTRACT; return m_fInteropLogArguments; }
unsigned fPInvokeRestoreEsp; // -1=Default, 0=Never, Else=Always
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- bool fLegacyCorruptedStateExceptionsPolicy;
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
-
LPUTF8 pszBreakOnClassLoad; // Halt just before loading this class
#ifdef TEST_DATA_CONSISTENCY
#ifndef FEATURE_REDHAWK
}
EX_CATCH { }
- EX_END_CATCH(RethrowCorruptingExceptions);
+ EX_END_CATCH(RethrowTerminalExceptions);
#endif // FEATURE_REDHAWK
return hr;
{
fSucceeded = FALSE;
}
- EX_END_CATCH(RethrowCorruptingExceptions);
+ EX_END_CATCH(RethrowTerminalExceptions);
if (!fSucceeded)
return -1;
{
fSucceeded = FALSE;
}
- EX_END_CATCH(RethrowCorruptingExceptions);
+ EX_END_CATCH(RethrowTerminalExceptions);
if (!fSucceeded)
return -1;
}
{
fSucceeded = FALSE;
}
- EX_END_CATCH(RethrowCorruptingExceptions);
+ EX_END_CATCH(RethrowTerminalExceptions);
if (!fSucceeded)
return -1;
}
{
fSucceeded = FALSE;
}
- EX_END_CATCH(RethrowCorruptingExceptions);
+ EX_END_CATCH(RethrowTerminalExceptions);
if (!fSucceeded)
return -1;
}
// won't have a name in it.
pVal->sName.Clear();
}
- EX_END_CATCH(RethrowCorruptingExceptions);
+ EX_END_CATCH(RethrowTerminalExceptions);
// Now that we know the full size of this type's data, see if it fits in our
// batch or whether we need to flush
{
fSucceeded = FALSE;
}
- EX_END_CATCH(RethrowCorruptingExceptions);
+ EX_END_CATCH(RethrowTerminalExceptions);
if (!fSucceeded)
return;
EX_CATCH
{
}
- EX_END_CATCH(RethrowCorruptingExceptions);
+ EX_END_CATCH(RethrowTerminalExceptions);
}
}
{
fSucceeded = FALSE;
}
- EX_END_CATCH(RethrowCorruptingExceptions);
+ EX_END_CATCH(RethrowTerminalExceptions);
return fSucceeded;
}
{
fSucceeded = FALSE;
}
- EX_END_CATCH(RethrowCorruptingExceptions);
+ EX_END_CATCH(RethrowTerminalExceptions);
if (!fSucceeded)
{
*pfCreatedNew = FALSE;
{
fSucceeded = FALSE;
}
- EX_END_CATCH(RethrowCorruptingExceptions);
+ EX_END_CATCH(RethrowTerminalExceptions);
if (!fSucceeded)
{
*pfCreatedNew = FALSE;
{
fSucceeded = FALSE;
}
- EX_END_CATCH(RethrowCorruptingExceptions);
+ EX_END_CATCH(RethrowTerminalExceptions);
if (!fSucceeded)
{
*pfCreatedNew = FALSE;
{
fSucceeded = FALSE;
}
- EX_END_CATCH(RethrowCorruptingExceptions);
+ EX_END_CATCH(RethrowTerminalExceptions);
if (!fSucceeded)
{
*pfCreatedNew = FALSE;
pExInfo = pExState->GetCurrentExceptionTracker();
_ASSERTE(pExInfo != NULL);
bIsNestedException = (pExInfo->GetPreviousExceptionTracker() != NULL);
- bIsCSE = (pExInfo->GetCorruptionSeverity() == ProcessCorrupting);
bIsCLSCompliant = IsException((gc.exceptionObj)->GetMethodTable()) &&
((gc.exceptionObj)->GetMethodTable() != MscorlibBinder::GetException(kRuntimeWrappedException));
exceptionFlags = ((bHasInnerException ? ETW::ExceptionLog::ExceptionStructs::HasInnerException : 0) |
(bIsNestedException ? ETW::ExceptionLog::ExceptionStructs::IsNestedException : 0) |
(bIsReThrownException ? ETW::ExceptionLog::ExceptionStructs::IsReThrownException : 0) |
- (bIsCSE ? ETW::ExceptionLog::ExceptionStructs::IsCSE : 0) |
(bIsCLSCompliant ? ETW::ExceptionLog::ExceptionStructs::IsCLSCompliant : 0));
if (pCf->IsFrameless())
{
fSucceeded = FALSE;
}
- EX_END_CATCH(RethrowCorruptingExceptions);
+ EX_END_CATCH(RethrowTerminalExceptions);
if (!fSucceeded)
goto done;
PEXCEPTION_REGISTRATION_RECORD GetCurrentSEHRecord();
BOOL IsUnmanagedToManagedSEHHandler(EXCEPTION_REGISTRATION_RECORD*);
-VOID DECLSPEC_NORETURN RealCOMPlusThrow(OBJECTREF throwable, BOOL rethrow
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- , CorruptionSeverity severity = NotCorrupting
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
- );
+VOID DECLSPEC_NORETURN RealCOMPlusThrow(OBJECTREF throwable, BOOL rethrow);
//-------------------------------------------------------------------------------
// Basically, this asks whether the exception is a managed exception thrown by
return EXCEPTION_CONTINUE_SEARCH;
}
-//==========================================================================
-// Throw an object.
-//==========================================================================
-VOID DECLSPEC_NORETURN RaiseTheException(OBJECTREF throwable, BOOL rethrow
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- , CorruptionSeverity severity
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
- )
-{
- STATIC_CONTRACT_THROWS;
- STATIC_CONTRACT_GC_TRIGGERS;
- STATIC_CONTRACT_MODE_COOPERATIVE;
-
- LOG((LF_EH, LL_INFO100, "RealCOMPlusThrow throwing %s\n",
- throwable->GetMethodTable()->GetDebugClassName()));
-
- if (throwable == NULL)
- {
- _ASSERTE(!"RealCOMPlusThrow(OBJECTREF) called with NULL argument. Somebody forgot to post an exception!");
- EEPOLICY_HANDLE_FATAL_ERROR(COR_E_EXECUTIONENGINE);
- }
-
- _ASSERTE(throwable != CLRException::GetPreallocatedStackOverflowException());
-
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- if (!g_pConfig->LegacyCorruptedStateExceptionsPolicy())
- {
- // This is Scenario 3 described in clrex.h around the definition of SET_CE_RETHROW_FLAG_FOR_EX_CATCH macro.
- //
- // We are here because the VM is attempting to throw a managed exception. It is posssible this exception
- // may not be seen by CLR's exception handler for managed code (e.g. there maybe an EX_CATCH up the stack
- // that will swallow or rethrow this exception). In the following scenario:
- //
- // [VM1 - RethrowCSE] -> [VM2 - RethrowCSE] -> [VM3 - RethrowCSE] -> <managed code>
- //
- // When managed code throws a CSE (e.g. TargetInvocationException flagged as CSE), [VM3] will rethrow it and we will
- // enter EX_CATCH in VM2 which is supposed to rethrow it as well. Two things can happen:
- //
- // 1) The implementation of EX_CATCH in VM2 throws a new managed exception *before* rethrow policy is applied and control
- // will reach EX_CATCH in VM1, OR
- //
- // 2) EX_CATCH in VM2 swallows the exception, comes out of the catch block and later throws a new managed exception that
- // will be caught by EX_CATCH in VM1.
- //
- // In either of the cases, rethrow in VM1 should be on the basis of the new managed exception's corruption severity.
- //
- // To support this scenario, we set corruption severity of the managed exception VM is throwing. If its a rethrow,
- // it implies we are rethrowing the last exception that was seen by CLR's managed code exception handler. In such a case,
- // we will copy over the corruption severity of that exception.
-
- // If throwable indicates corrupted state, forcibly set the severity.
- if (CEHelper::IsProcessCorruptedStateException(throwable))
- {
- severity = ProcessCorrupting;
- }
-
- // No one should have passed us an invalid severity.
- _ASSERTE(severity > NotSet);
-
- if (severity == NotSet)
- {
- severity = NotCorrupting;
- }
-
- // Update the corruption severity of the exception being thrown by the VM.
- GetThread()->GetExceptionState()->SetLastActiveExceptionCorruptionSeverity(severity);
-
- // Exception's corruption severity should be reused in reraise if this exception leaks out from the VM
- // into managed code
- CEHelper::MarkLastActiveExceptionCorruptionSeverityForReraiseReuse();
-
- LOG((LF_EH, LL_INFO100, "RaiseTheException - Set VM thrown managed exception severity to %d.\n", severity));
- }
-
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
-
- RaiseTheExceptionInternalOnly(throwable,rethrow);
-}
-
HRESULT GetHRFromThrowable(OBJECTREF throwable)
{
STATIC_CONTRACT_THROWS;
// INSTALL_COMPLUS_EXCEPTION_HANDLER has a filter, so must put the call in a separate fcn
-static VOID DECLSPEC_NORETURN RealCOMPlusThrowWorker(OBJECTREF throwable, BOOL rethrow
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- , CorruptionSeverity severity
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
-) {
+static VOID DECLSPEC_NORETURN RealCOMPlusThrowWorker(OBJECTREF throwable, BOOL rethrow)
+{
STATIC_CONTRACT_THROWS;
STATIC_CONTRACT_GC_TRIGGERS;
STATIC_CONTRACT_MODE_ANY;
// TODO: Do we need to install COMPlusFrameHandler here?
INSTALL_COMPLUS_EXCEPTION_HANDLER();
- RaiseTheException(throwable, rethrow
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- , severity
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
- );
+ if (throwable == NULL)
+ {
+ _ASSERTE(!"RealCOMPlusThrow(OBJECTREF) called with NULL argument. Somebody forgot to post an exception!");
+ EEPOLICY_HANDLE_FATAL_ERROR(COR_E_EXECUTIONENGINE);
+ }
+ RaiseTheExceptionInternalOnly(throwable, rethrow);
UNINSTALL_COMPLUS_EXCEPTION_HANDLER();
}
-
-VOID DECLSPEC_NORETURN RealCOMPlusThrow(OBJECTREF throwable, BOOL rethrow
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- , CorruptionSeverity severity
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
-) {
+VOID DECLSPEC_NORETURN RealCOMPlusThrow(OBJECTREF throwable, BOOL rethrow)
+{
STATIC_CONTRACT_THROWS;
STATIC_CONTRACT_GC_TRIGGERS;
STATIC_CONTRACT_MODE_ANY;
+
+ LOG((LF_EH, LL_INFO100, "RealCOMPlusThrow throwing %s\n",
+ throwable->GetMethodTable()->GetDebugClassName()));
+
GCPROTECT_BEGIN(throwable);
_ASSERTE(IsException(throwable->GetMethodTable()));
ExceptionPreserveStackTrace(throwable);
}
- RealCOMPlusThrowWorker(throwable, rethrow
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- , severity
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
- );
+ RealCOMPlusThrowWorker(throwable, rethrow);
GCPROTECT_END();
}
-VOID DECLSPEC_NORETURN RealCOMPlusThrow(OBJECTREF throwable
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- , CorruptionSeverity severity
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
- )
+VOID DECLSPEC_NORETURN RealCOMPlusThrow(OBJECTREF throwable)
{
CONTRACTL
{
}
CONTRACTL_END;
- RealCOMPlusThrow(throwable, FALSE
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- , severity
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
- );
+ RealCOMPlusThrow(throwable, FALSE);
}
// this function finds the managed callback to get a resource
if (OBJECTREFToObject(*pThrowable)->GetMethodTable() == g_pExecutionEngineExceptionClass)
return TRUE;
-
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- // Corrupting exceptions are also uncatchable
- if (CEHelper::IsProcessCorruptedStateException(*pThrowable))
- {
- return TRUE;
- }
-#endif //FEATURE_CORRUPTING_EXCEPTIONS
}
return FALSE;
}
#endif // !TARGET_UNIX
- // If the application has opted into triggering a failfast when a CorruptedStateException enters the Reflection system,
- // then do the needful.
- if (CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_FailFastOnCorruptedStateException) == 1)
- {
- // Get the thread and the managed exception object - they must exist at this point
- Thread *pCurThread = GetThread();
- _ASSERTE(pCurThread != NULL);
-
- // Get the thread exception state
- ThreadExceptionState * pCurTES = pCurThread->GetExceptionState();
- _ASSERTE(pCurTES != NULL);
-
- // Get the exception tracker for the current exception
-#ifdef FEATURE_EH_FUNCLETS
- PTR_ExceptionTracker pEHTracker = pCurTES->GetCurrentExceptionTracker();
-#elif TARGET_X86
- PTR_ExInfo pEHTracker = pCurTES->GetCurrentExceptionTracker();
-#else // !(HOST_64BIT || TARGET_X86)
-#error Unsupported platform
-#endif // HOST_64BIT
-
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- if (pEHTracker->GetCorruptionSeverity() == ProcessCorrupting)
- {
- EEPolicy::HandleFatalError(COR_E_FAILFAST, reinterpret_cast<UINT_PTR>(pExceptionInfo->ExceptionRecord->ExceptionAddress), NULL, pExceptionInfo);
- }
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
- }
-
return ret;
} // LONG ReflectionInvocationExceptionFilter()
return fFoundTracker ? pEHTracker : NULL;
}
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
-// -----------------------------------------------------------------------
-// Support for CorruptedState Exceptions
-// -----------------------------------------------------------------------
-
// Given an exception code, this method returns a BOOL to indicate if the
// code belongs to a corrupting exception or not.
/* static */
-BOOL CEHelper::IsProcessCorruptedStateException(DWORD dwExceptionCode, BOOL fCheckForSO /*= TRUE*/)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- if (g_pConfig->LegacyCorruptedStateExceptionsPolicy())
- {
- return FALSE;
- }
-
- // Call into the utilcode helper function to check if this
- // is a CE or not.
- return (::IsProcessCorruptedStateException(dwExceptionCode, fCheckForSO));
-}
-
-// This is used in the VM folder version of "SET_CE_RETHROW_FLAG_FOR_EX_CATCH" (in clrex.h)
-// to check if the managed exception caught by EX_END_CATCH is CSE or not.
-//
-// If you are using it from rethrow boundaries (e.g. SET_CE_RETHROW_FLAG_FOR_EX_CATCH
-// macro that is used to automatically rethrow corrupting exceptions), then you may
-// want to set the "fMarkForReuseIfCorrupting" to TRUE to enable propagation of the
-// corruption severity when the reraised exception is seen by managed code again.
-/* static */
-BOOL CEHelper::IsLastActiveExceptionCorrupting(BOOL fMarkForReuseIfCorrupting /* = FALSE */)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(GetThread() != NULL);
- }
- CONTRACTL_END;
-
- if (g_pConfig->LegacyCorruptedStateExceptionsPolicy())
- {
- return FALSE;
- }
-
- BOOL fIsCorrupting = FALSE;
- ThreadExceptionState *pCurTES = GetThread()->GetExceptionState();
-
- // Check the corruption severity
- CorruptionSeverity severity = pCurTES->GetLastActiveExceptionCorruptionSeverity();
- fIsCorrupting = (severity == ProcessCorrupting);
- if (fIsCorrupting && fMarkForReuseIfCorrupting)
- {
- // Mark the corruption severity for reuse
- CEHelper::MarkLastActiveExceptionCorruptionSeverityForReraiseReuse();
- }
-
- LOG((LF_EH, LL_INFO100, "CEHelper::IsLastActiveExceptionCorrupting - Using corruption severity from TES.\n"));
-
- return fIsCorrupting;
-}
-
-// Given a MethodDesc, this method will return a BOOL to indicate if
-// the containing assembly was built for PreV4 runtime or not.
-/* static */
-BOOL CEHelper::IsMethodInPreV4Assembly(PTR_MethodDesc pMethodDesc)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(pMethodDesc != NULL);
- }
- CONTRACTL_END;
-
- // By default, assume that the containing assembly was not
- // built for PreV4 runtimes.
- BOOL fBuiltForPreV4Runtime = FALSE;
-
- if (g_pConfig->LegacyCorruptedStateExceptionsPolicy())
- {
- return TRUE;
- }
-
- LPCSTR pszVersion = NULL;
-
- // Retrieve the manifest metadata reference since that contains
- // the "built-for" runtime details
- IMDInternalImport *pImport = pMethodDesc->GetAssembly()->GetManifestImport();
- if (pImport && SUCCEEDED(pImport->GetVersionString(&pszVersion)))
- {
- if (pszVersion != NULL)
- {
- // If version begins with "v1.*" or "v2.*", it was built for preV4 runtime
- if ((pszVersion[0] == 'v' || pszVersion[0] == 'V') &&
- IS_DIGIT(pszVersion[1]) &&
- (pszVersion[2] == '.') )
- {
- // Looks like a version. Is it lesser than v4.0 major version where we start using new behavior?
- fBuiltForPreV4Runtime = ((DIGIT_TO_INT(pszVersion[1]) != 0) &&
- (DIGIT_TO_INT(pszVersion[1]) <= HIGHEST_MAJOR_VERSION_OF_PREV4_RUNTIME));
- }
- }
- }
-
- return fBuiltForPreV4Runtime;
-}
-
-// Given a MethodDesc and CorruptionSeverity, this method will return a
-// BOOL indicating if the method can handle those kinds of CEs or not.
-/* static */
-BOOL CEHelper::CanMethodHandleCE(PTR_MethodDesc pMethodDesc, CorruptionSeverity severity)
-{
- BOOL fCanMethodHandleSeverity = FALSE;
-
-#ifndef DACCESS_COMPILE
- CONTRACTL
- {
- GC_NOTRIGGER;
- THROWS;
- MODE_ANY;
- PRECONDITION(pMethodDesc != NULL);
- }
- CONTRACTL_END;
-
-
- if (g_pConfig->LegacyCorruptedStateExceptionsPolicy())
- {
- return TRUE;
- }
-
- // Since the method is Security Critical, now check if it is
- // attributed to handle the CE or not.
- IMDInternalImport *pImport = pMethodDesc->GetMDImport();
- if (pImport != NULL)
- {
- mdMethodDef methodDef = pMethodDesc->GetMemberDef();
- switch(severity)
- {
- case ProcessCorrupting:
- fCanMethodHandleSeverity = (S_OK == pImport->GetCustomAttributeByName(
- methodDef,
- HANDLE_PROCESS_CORRUPTED_STATE_EXCEPTION_ATTRIBUTE,
- NULL,
- NULL));
- break;
- default:
- _ASSERTE(!"Unknown Exception Corruption Severity!");
- break;
- }
- }
-#endif // !DACCESS_COMPILE
-
- return fCanMethodHandleSeverity;
-}
-
-// Given a MethodDesc, this method will return a BOOL to indicate if the method should be examined for exception
-// handlers for the specified exception.
-//
-// This method accounts for both corrupting and non-corrupting exceptions.
-/* static */
-BOOL CEHelper::CanMethodHandleException(CorruptionSeverity severity, PTR_MethodDesc pMethodDesc)
-{
- CONTRACTL
- {
- GC_NOTRIGGER;
- THROWS;
- MODE_ANY;
- PRECONDITION(pMethodDesc != NULL);
- }
- CONTRACTL_END;
-
- // By default, assume that the runtime shouldn't look for exception handlers
- // in the method pointed by the MethodDesc
- BOOL fLookForExceptionHandlersInMethod = FALSE;
-
- if (g_pConfig->LegacyCorruptedStateExceptionsPolicy())
- {
- return TRUE;
- }
-
- // If we have been asked to use the last active corruption severity (e.g. in cases of Reflection
- // or COM interop), then retrieve it.
- if (severity == UseLast)
- {
- LOG((LF_EH, LL_INFO100, "CEHelper::CanMethodHandleException - Using LastActiveExceptionCorruptionSeverity.\n"));
- severity = GetThread()->GetExceptionState()->GetLastActiveExceptionCorruptionSeverity();
- }
-
- LOG((LF_EH, LL_INFO100, "CEHelper::CanMethodHandleException - Processing CorruptionSeverity: %d.\n", severity));
-
- if (severity > NotCorrupting)
- {
- // If the method lies in an assembly built for pre-V4 runtime, allow the runtime
- // to look for exception handler for the CE.
- BOOL fIsMethodInPreV4Assembly = FALSE;
- fIsMethodInPreV4Assembly = CEHelper::IsMethodInPreV4Assembly(pMethodDesc);
-
- if (!fIsMethodInPreV4Assembly)
- {
- // Method lies in an assembly built for V4 or later runtime.
- LOG((LF_EH, LL_INFO100, "CEHelper::CanMethodHandleException - Method is in an assembly built for V4 or later runtime.\n"));
-
- // Depending upon the corruption severity of the exception, see if the
- // method supports handling that.
- LOG((LF_EH, LL_INFO100, "CEHelper::CanMethodHandleException - Exception is corrupting.\n"));
-
- // Check if the method can handle the severity specified in the exception object.
- fLookForExceptionHandlersInMethod = CEHelper::CanMethodHandleCE(pMethodDesc, severity);
- }
- else
- {
- // Method is in a Pre-V4 assembly - allow it to be examined for processing the CE
- fLookForExceptionHandlersInMethod = TRUE;
- }
- }
- else
- {
- // Non-corrupting exceptions can continue to be delivered
- fLookForExceptionHandlersInMethod = TRUE;
- }
-
- return fLookForExceptionHandlersInMethod;
-}
-
-// Given a managed exception object, this method will return a BOOL
-// indicating if it corresponds to a ProcessCorruptedState exception
-// or not.
-/* static */
-BOOL CEHelper::IsProcessCorruptedStateException(OBJECTREF oThrowable)
+BOOL IsProcessCorruptedStateException(DWORD dwExceptionCode, OBJECTREF throwable)
{
CONTRACTL
{
NOTHROW;
GC_NOTRIGGER;
MODE_COOPERATIVE;
- PRECONDITION(oThrowable != NULL);
}
CONTRACTL_END;
- if (g_pConfig->LegacyCorruptedStateExceptionsPolicy())
+ switch (dwExceptionCode)
{
+ case STATUS_ACCESS_VIOLATION:
+ if (throwable != NULL && MscorlibBinder::IsException(throwable->GetMethodTable(), kNullReferenceException))
+ return FALSE;
+ break;
+ case STATUS_STACK_OVERFLOW:
+ case EXCEPTION_ILLEGAL_INSTRUCTION:
+ case EXCEPTION_IN_PAGE_ERROR:
+ case EXCEPTION_INVALID_DISPOSITION:
+ case EXCEPTION_NONCONTINUABLE_EXCEPTION:
+ case EXCEPTION_PRIV_INSTRUCTION:
+ case STATUS_UNWIND_CONSOLIDATE:
+ break;
+ default:
return FALSE;
}
-#ifndef DACCESS_COMPILE
- // If the throwable represents preallocated SO, then indicate it as a CSE
- if (CLRException::GetPreallocatedStackOverflowException() == oThrowable)
- {
- return TRUE;
- }
-#endif // !DACCESS_COMPILE
-
- // Check if we have an exception tracker for this exception
- // and if so, if it represents corrupting exception or not.
- // Get the exception tracker for the current exception
-#ifdef FEATURE_EH_FUNCLETS
- PTR_ExceptionTracker pEHTracker = GetEHTrackerForException(oThrowable, NULL);
-#elif TARGET_X86
- PTR_ExInfo pEHTracker = GetEHTrackerForException(oThrowable, NULL);
-#else
-#error Unsupported platform
-#endif
-
- if (pEHTracker != NULL)
- {
- // Found the tracker for exception object - check if its CSE or not.
- return (pEHTracker->GetCorruptionSeverity() == ProcessCorrupting);
- }
-
- return FALSE;
-}
-
-#ifdef FEATURE_EH_FUNCLETS
-void CEHelper::SetupCorruptionSeverityForActiveExceptionInUnwindPass(Thread *pCurThread, PTR_ExceptionTracker pEHTracker, BOOL fIsFirstPass,
- DWORD dwExceptionCode)
-{
-#ifndef DACCESS_COMPILE
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(!fIsFirstPass); // This method should only be called during an unwind
- PRECONDITION(pCurThread != NULL);
- }
- CONTRACTL_END;
-
- // <WIN64>
- //
- // Typically, exception tracker is created for an exception when the OS is in the first pass.
- // However, it may be created during the 2nd pass under specific cases. Managed C++ provides
- // such a scenario. In the following, stack grows left to right:
- //
- // CallDescrWorker -> ILStub1 -> <Native Main> -> UMThunkStub -> IL_Stub2 -> <Managed Main>
- //
- // If a CSE exception goes unhandled from managed main, it will reach the OS. The [CRT in?] OS triggers
- // unwind that results in invoking the personality routine of UMThunkStub, called UMThunkStubUnwindFrameChainHandler,
- // that releases all exception trackers below it. Thus, the tracker for the CSE, which went unhandled, is also
- // released. This detail is 64bit specific and the crux of this issue.
- //
- // Now, it is expected that by the time we are in the unwind pass, the corruption severity would have already been setup in the
- // exception tracker and thread exception state (TES) as part of the first pass, and thus, are identical.
- //
- // However, for the scenario above, when the unwind continues and reaches ILStub1, its personality routine (which is ProcessCLRException)
- // is invoked. It attempts to get the exception tracker corresponding to the exception. Since none exists, it creates a brand new one,
- // which has the exception corruption severity as NotSet.
- //
- // During the stack walk, we know (from TES) that the active exception was a CSE, and thus, ILStub1 cannot handle the exception. Prior
- // to bailing out, we assert that our data structures are intact by comparing the exception severity in TES with the one in the current
- // exception tracker. Since the tracker was recreated, it had the severity as NotSet and this does not match the severity in TES.
- // Thus, the assert fires. [This check is performed in ProcessManagedCallFrame.]
- //
- // To address such a case, if we have created a new exception tracker in the unwind (2nd) pass, then set its
- // exception corruption severity to what the TES holds currently. This will maintain the same semantic as the case
- // where new tracker is not created (for e.g. the exception was caught in Managed main).
- //
- // The exception is the scenario of code that uses longjmp to jump to a different context. Longjmp results in a raise
- // of a new exception with the longjmp exception code (0x80000026) but with ExceptionFlags set indicating unwind. When this is
- // seen by ProcessCLRException (64bit personality routine), it will create a new tracker in the 2nd pass.
- //
- // Longjmp outside an exceptional path does not interest us, but the one in the exceptional
- // path would only happen when a method attributed to handle CSE invokes it. Thus, if the longjmp happened during the 2nd pass of a CSE,
- // we want it to proceed (and thus, jump) as expected and not apply the CSE severity to the tracker - this is equivalent to
- // a catch block that handles a CSE and then does a "throw new Exception();". The new exception raised is
- // non-CSE in nature as well.
- //
- // http://www.nynaeve.net/?p=105 has a brief description of how exception-safe setjmp/longjmp works.
- //
- // </WIN64>
- if (pEHTracker->GetCorruptionSeverity() == NotSet)
- {
- // Get the thread exception state
- ThreadExceptionState *pCurTES = pCurThread->GetExceptionState();
-
- // Set the tracker to have the same corruption severity as the last active severity unless we are dealing
- // with LONGJMP
- if (dwExceptionCode == STATUS_LONGJUMP)
- {
- pCurTES->SetLastActiveExceptionCorruptionSeverity(NotCorrupting);
- }
-
- pEHTracker->SetCorruptionSeverity(pCurTES->GetLastActiveExceptionCorruptionSeverity());
- LOG((LF_EH, LL_INFO100, "CEHelper::SetupCorruptionSeverityForActiveExceptionInUnwindPass - Setup the corruption severity in the second pass.\n"));
- }
-#endif // !DACCESS_COMPILE
-}
-#endif // FEATURE_EH_FUNCLETS
-
-// This method is invoked from the personality routine for managed code and is used to setup the
-// corruption severity for the active exception on the thread exception state and the
-// exception tracker corresponding to the exception.
-/* static */
-void CEHelper::SetupCorruptionSeverityForActiveException(BOOL fIsRethrownException, BOOL fIsNestedException, BOOL fShouldTreatExceptionAsNonCorrupting /* = FALSE */)
-{
-#ifndef DACCESS_COMPILE
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_COOPERATIVE;
- }
- CONTRACTL_END;
-
- // Get the thread and the managed exception object - they must exist at this point
- Thread *pCurThread = GetThread();
- _ASSERTE(pCurThread != NULL);
-
- OBJECTREF oThrowable = pCurThread->GetThrowable();
- _ASSERTE(oThrowable != NULL);
-
- // Get the thread exception state
- ThreadExceptionState * pCurTES = pCurThread->GetExceptionState();
- _ASSERTE(pCurTES != NULL);
-
- // Get the exception tracker for the current exception
-#ifdef FEATURE_EH_FUNCLETS
- PTR_ExceptionTracker pEHTracker = pCurTES->GetCurrentExceptionTracker();
-#elif TARGET_X86
- PTR_ExInfo pEHTracker = pCurTES->GetCurrentExceptionTracker();
-#else // !(HOST_64BIT || TARGET_X86)
-#error Unsupported platform
-#endif // HOST_64BIT
-
- _ASSERTE(pEHTracker != NULL);
-
- // Get the current exception code from the tracker.
- PEXCEPTION_RECORD pEHRecord = pCurTES->GetExceptionRecord();
- _ASSERTE(pEHRecord != NULL);
- DWORD dwActiveExceptionCode = pEHRecord->ExceptionCode;
-
- if (pEHTracker->GetCorruptionSeverity() != NotSet)
- {
- // Since the exception tracker already has the corruption severity set,
- // we dont have much to do. Just confirm that our assumptions are correct.
- _ASSERTE(pEHTracker->GetCorruptionSeverity() == pCurTES->GetLastActiveExceptionCorruptionSeverity());
-
- LOG((LF_EH, LL_INFO100, "CEHelper::SetupCorruptionSeverityForActiveException - Current tracker already has the corruption severity set.\n"));
- return;
- }
-
- // If the exception in question is to be treated as non-corrupting,
- // then flag it and exit.
- if (fShouldTreatExceptionAsNonCorrupting || g_pConfig->LegacyCorruptedStateExceptionsPolicy())
- {
- pEHTracker->SetCorruptionSeverity(NotCorrupting);
- LOG((LF_EH, LL_INFO100, "CEHelper::SetupCorruptionSeverityForActiveException - Exception treated as non-corrupting.\n"));
- goto done;
- }
-
- if (!fIsRethrownException && !fIsNestedException)
- {
- // There should be no previously active exception for this case
- _ASSERTE(pEHTracker->GetPreviousExceptionTracker() == NULL);
-
- CorruptionSeverity severityTES = NotSet;
-
- if (pCurTES->ShouldLastActiveExceptionCorruptionSeverityBeReused())
- {
- // Get the corruption severity from the ThreadExceptionState (TES) for the last active exception
- severityTES = pCurTES->GetLastActiveExceptionCorruptionSeverity();
-
- // Incase of scenarios like AD transition or Reflection invocation,
- // TES would hold corruption severity of the last active exception. To propagate it
- // to the current exception, we will apply it to current tracker and only if the applied
- // severity is "NotSet", will we proceed to check the current exception for corruption
- // severity.
- pEHTracker->SetCorruptionSeverity(severityTES);
- }
-
- // Reset TES Corruption Severity
- pCurTES->SetLastActiveExceptionCorruptionSeverity(NotSet);
-
- if (severityTES == NotSet)
- {
- // Since the last active exception's severity was "NotSet", we will look up the
- // exception code and the exception object to see if the exception should be marked
- // corrupting.
- //
- // Since this exception was neither rethrown nor is nested, it implies that we are
- // outside an active exception. Thus, even if it contains inner exceptions, we wont have
- // corruption severity for them since that information is tracked in EH tracker and
- // we wont have an EH tracker for the inner most exception.
-
- if (CEHelper::IsProcessCorruptedStateException(dwActiveExceptionCode) ||
- CEHelper::IsProcessCorruptedStateException(oThrowable))
- {
- pEHTracker->SetCorruptionSeverity(ProcessCorrupting);
- LOG((LF_EH, LL_INFO100, "CEHelper::SetupCorruptionSeverityForActiveException - Marked non-rethrow/non-nested exception as ProcessCorrupting.\n"));
- }
- else
- {
- pEHTracker->SetCorruptionSeverity(NotCorrupting);
- LOG((LF_EH, LL_INFO100, "CEHelper::SetupCorruptionSeverityForActiveException - Marked non-rethrow/non-nested exception as NotCorrupting.\n"));
- }
- }
- else
- {
- LOG((LF_EH, LL_INFO100, "CEHelper::SetupCorruptionSeverityForActiveException - Copied the corruption severity to tracker from ThreadExceptionState for non-rethrow/non-nested exception.\n"));
- }
- }
- else
- {
- // Its either a rethrow or nested exception
-
-#ifdef FEATURE_EH_FUNCLETS
- PTR_ExceptionTracker pOrigEHTracker = NULL;
-#elif TARGET_X86
- PTR_ExInfo pOrigEHTracker = NULL;
-#else
-#error Unsupported platform
-#endif
-
- BOOL fDoWeHaveCorruptionSeverity = FALSE;
-
- if (fIsRethrownException)
- {
- // Rethrown exceptions are nested by nature (of our implementation). The
- // original EHTracker will exist for the exception - infact, it will be
- // the tracker previous to the current one. We will simply copy
- // its severity to the current EH tracker representing the rethrow.
- pOrigEHTracker = pEHTracker->GetPreviousExceptionTracker();
- _ASSERTE(pOrigEHTracker != NULL);
-
- // Ideally, we would like have the assert below enabled. But, as may happen under OOM
- // stress, this can be false. Here's how it will happen:
- //
- // An exception is thrown, which is later caught and rethrown in the catch block. Rethrow
- // results in calling IL_Rethrow that will call RaiseTheExceptionInternalOnly to actually
- // raise the exception. Prior to the raise, we update the last thrown object on the thread
- // by calling Thread::SafeSetLastThrownObject which, internally, could have an OOM, resulting
- // in "changing" the throwable used to raise the exception to be preallocated OOM object.
- //
- // When the rethrow happens and CLR's exception handler for managed code sees the exception,
- // the exception tracker created for the rethrown exception will contain the reference to
- // the last thrown object, which will be the preallocated OOM object.
- //
- // Thus, though, we came here because of a rethrow, and logically, the throwable should remain
- // the same, it neednt be. Simply put, rethrow can result in working with a completely different
- // exception object than what was originally thrown.
- //
- // Hence, the assert cannot be enabled.
- //
- // Thus, we will use the EH tracker corresponding to the original exception, to get the
- // rethrown exception's corruption severity, only when the rethrown throwable is the same
- // as the original throwable. Otherwise, we will pretend that we didnt get the original tracker
- // and will automatically enter the path below to set the corruption severity based upon the
- // rethrown throwable.
-
- // _ASSERTE(pOrigEHTracker->GetThrowable() == oThrowable);
- if (pOrigEHTracker->GetThrowable() != oThrowable)
- {
- pOrigEHTracker = NULL;
- LOG((LF_EH, LL_INFO100, "CEHelper::SetupCorruptionSeverityForActiveException - Rethrown throwable does not match the original throwable. Corruption severity will be set based upon rethrown throwable.\n"));
- }
- }
- else
- {
- // Get the corruption severity from the ThreadExceptionState (TES) for the last active exception
- CorruptionSeverity severityTES = NotSet;
-
- if (pCurTES->ShouldLastActiveExceptionCorruptionSeverityBeReused())
- {
- severityTES = pCurTES->GetLastActiveExceptionCorruptionSeverity();
-
- // Incase of scenarios like AD transition or Reflection invocation,
- // TES would hold corruption severity of the last active exception. To propagate it
- // to the current exception, we will apply it to current tracker and only if the applied
- // severity is "NotSet", will we proceed to check the current exception for corruption
- // severity.
- pEHTracker->SetCorruptionSeverity(severityTES);
- }
-
- // Reset TES Corruption Severity
- pCurTES->SetLastActiveExceptionCorruptionSeverity(NotSet);
-
- // If the last exception didnt have any corruption severity, proceed to look for it.
- if (severityTES == NotSet)
- {
- // This is a nested exception - check if it has an inner exception(s). If it does,
- // find the EH tracker corresponding to the innermost exception and we will copy the
- // corruption severity from the original tracker to the current one.
- OBJECTREF oInnermostThrowable = ((EXCEPTIONREF)oThrowable)->GetBaseException();
- if (oInnermostThrowable != NULL)
- {
- // Find the tracker corresponding to the inner most exception, starting from
- // the tracker previous to the current one. An EH tracker may not be found if
- // the code did the following inside a catch clause:
- //
- // Exception ex = new Exception("inner exception");
- // throw new Exception("message", ex);
- //
- // Or, an exception like AV happened in the catch clause.
- pOrigEHTracker = GetEHTrackerForException(oInnermostThrowable, pEHTracker->GetPreviousExceptionTracker());
- }
- }
- else
- {
- // We have the corruption severity from the TES. Set the flag indicating so.
- fDoWeHaveCorruptionSeverity = TRUE;
- LOG((LF_EH, LL_INFO100, "CEHelper::SetupCorruptionSeverityForActiveException - Copied the corruption severity to tracker from ThreadExceptionState for nested exception.\n"));
- }
- }
-
- if (!fDoWeHaveCorruptionSeverity)
- {
- if (pOrigEHTracker != NULL)
- {
- // Copy the severity from the original EH tracker to the current one
- CorruptionSeverity origCorruptionSeverity = pOrigEHTracker->GetCorruptionSeverity();
- _ASSERTE(origCorruptionSeverity != NotSet);
- pEHTracker->SetCorruptionSeverity(origCorruptionSeverity);
-
- LOG((LF_EH, LL_INFO100, "CEHelper::SetupCorruptionSeverityForActiveException - Copied the corruption severity (%d) from the original EH tracker for rethrown exception.\n", origCorruptionSeverity));
- }
- else
- {
- if (CEHelper::IsProcessCorruptedStateException(dwActiveExceptionCode) ||
- CEHelper::IsProcessCorruptedStateException(oThrowable))
- {
- pEHTracker->SetCorruptionSeverity(ProcessCorrupting);
- LOG((LF_EH, LL_INFO100, "CEHelper::SetupCorruptionSeverityForActiveException - Marked nested exception as ProcessCorrupting.\n"));
- }
- else
- {
- pEHTracker->SetCorruptionSeverity(NotCorrupting);
- LOG((LF_EH, LL_INFO100, "CEHelper::SetupCorruptionSeverityForActiveException - Marked nested exception as NotCorrupting.\n"));
- }
- }
- }
- }
-
-done:
- // Save the current exception's corruption severity in the ThreadExceptionState (TES)
- // for cases when we catch the managed exception in the runtime using EX_CATCH.
- // At such a time, all exception trackers get released (due to unwind triggered
- // by EX_END_CATCH) and yet we need the corruption severity information for
- // scenarios like AD Transition, Reflection invocation, etc.
- CorruptionSeverity currentSeverity = pEHTracker->GetCorruptionSeverity();
-
- // We should be having a valid corruption severity at this point
- _ASSERTE(currentSeverity != NotSet);
-
- // Save it in the TES
- pCurTES->SetLastActiveExceptionCorruptionSeverity(currentSeverity);
- LOG((LF_EH, LL_INFO100, "CEHelper::SetupCorruptionSeverityForActiveException - Copied the corruption severity (%d) to ThreadExceptionState.\n", currentSeverity));
-
-#endif // !DACCESS_COMPILE
-}
-
-// CE can be caught in the VM and later reraised again. Examples of such scenarios
-// include AD transition, COM interop, Reflection invocation, to name a few.
-// In such cases, we want to mark the corruption severity for reuse upon reraise,
-// implying that when the VM does a reraise of such an exception, we should use
-// the original corruption severity for the new raised exception, instead of creating
-// a new one for it.
-/* static */
-void CEHelper::MarkLastActiveExceptionCorruptionSeverityForReraiseReuse()
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(GetThread() != NULL);
- }
- CONTRACTL_END;
-
- // If the last active exception's corruption severity is anything but
- // "NotSet", mark it for ReraiseReuse
- ThreadExceptionState *pCurTES = GetThread()->GetExceptionState();
- _ASSERTE(pCurTES != NULL);
-
- CorruptionSeverity severityTES = pCurTES->GetLastActiveExceptionCorruptionSeverity();
- if (severityTES != NotSet)
- {
- pCurTES->SetLastActiveExceptionCorruptionSeverity((CorruptionSeverity)(severityTES | ReuseForReraise));
- }
-}
-
-// This method will return a BOOL to indicate if the current exception is to be treated as
-// non-corrupting. Currently, this returns true for NullReferenceException only.
-/* static */
-BOOL CEHelper::ShouldTreatActiveExceptionAsNonCorrupting()
-{
- BOOL fShouldTreatAsNonCorrupting = FALSE;
-
-#ifndef DACCESS_COMPILE
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(GetThread() != NULL);
- }
- CONTRACTL_END;
-
- if (g_pConfig->LegacyCorruptedStateExceptionsPolicy())
- {
- return TRUE;
- }
-
- DWORD dwActiveExceptionCode = GetThread()->GetExceptionState()->GetExceptionRecord()->ExceptionCode;
- if (dwActiveExceptionCode == STATUS_ACCESS_VIOLATION)
- {
- // NullReference has the same exception code as AV
- OBJECTREF oThrowable = NULL;
- GCPROTECT_BEGIN(oThrowable);
-
- // Get the throwable and check if it represents null reference exception
- oThrowable = GetThread()->GetThrowable();
- _ASSERTE(oThrowable != NULL);
- if (MscorlibBinder::GetException(kNullReferenceException) == oThrowable->GetMethodTable())
- {
- fShouldTreatAsNonCorrupting = TRUE;
- }
- GCPROTECT_END();
- }
-#endif // !DACCESS_COMPILE
-
- return fShouldTreatAsNonCorrupting;
-}
-
-// If we were working in a nested exception scenario, reset the corruption severity to the last
-// exception we were processing, based upon its EH tracker.
-//
-// If none was present, reset it to NotSet.
-//
-// Note: This method must be called once the exception trackers have been adjusted post catch-block execution.
-/* static */
-void CEHelper::ResetLastActiveCorruptionSeverityPostCatchHandler(Thread *pThread)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(pThread != NULL);
- }
- CONTRACTL_END;
-
- ThreadExceptionState *pCurTES = pThread->GetExceptionState();
-
- // By this time, we would have set the correct exception tracker for the active exception domain,
- // if applicable. An example is throwing and catching an exception within a catch block. We will update
- // the LastActiveCorruptionSeverity based upon the active exception domain. If we are not in one, we will
- // set it to "NotSet".
-#ifdef FEATURE_EH_FUNCLETS
- PTR_ExceptionTracker pEHTracker = pCurTES->GetCurrentExceptionTracker();
-#elif TARGET_X86
- PTR_ExInfo pEHTracker = pCurTES->GetCurrentExceptionTracker();
-#else
-#error Unsupported platform
-#endif
-
- if (pEHTracker)
- {
- pCurTES->SetLastActiveExceptionCorruptionSeverity(pEHTracker->GetCorruptionSeverity());
- }
- else
- {
- pCurTES->SetLastActiveExceptionCorruptionSeverity(NotSet);
- }
-
- LOG((LF_EH, LL_INFO100, "CEHelper::ResetLastActiveCorruptionSeverityPostCatchHandler - Reset LastActiveException corruption severity to %d.\n",
- pCurTES->GetLastActiveExceptionCorruptionSeverity()));
-}
-
-// This method will return a BOOL indicating if the target of IDispatch can handle the specified exception or not.
-/* static */
-BOOL CEHelper::CanIDispatchTargetHandleException()
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(GetThread() != NULL);
- }
- CONTRACTL_END;
-
- // By default, assume that the target of IDispatch cannot handle the exception.
- BOOL fCanMethodHandleException = FALSE;
-
- if (g_pConfig->LegacyCorruptedStateExceptionsPolicy())
- {
- return TRUE;
- }
-
- // IDispatch implementation in COM interop works by invoking the actual target via reflection.
- // Thus, a COM client could use the V4 runtime to invoke a V2 method. In such a case, a CSE
- // could come unhandled at the actual target invoked via reflection.
- //
- // Reflection invocation would have set a flag for us, indicating if the actual target was
- // enabled to handle the CE or not. If it is, then we should allow the COM client to get the
- // hresult from the call and not let the exception continue up the stack.
- ThreadExceptionState *pCurTES = GetThread()->GetExceptionState();
- fCanMethodHandleException = pCurTES->CanReflectionTargetHandleException();
-
- // Reset the flag so that subsequent invocations work as expected.
- pCurTES->SetCanReflectionTargetHandleException(FALSE);
+ if (CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_legacyCorruptedStateExceptionsPolicy))
+ return FALSE;
- return fCanMethodHandleException;
+ return TRUE;
}
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
-
#ifndef DACCESS_COMPILE
// This method will deliver the actual exception notification. Its assumed that the caller has done the necessary checks, including
// checking whether the delegate can be invoked for the exception's corruption severity.
*pOutEventArgs = NULL;
LOG((LF_EH, LL_INFO100, "ExceptionNotifications::GetEventArgsForNotification: Setting event args to NULL due to an exception.\n"));
}
- EX_END_CATCH(RethrowCorruptingExceptions); // Dont swallow any CSE that may come in from the .ctor.
+ EX_END_CATCH(RethrowTerminalExceptions);
}
// This SEH filter will be invoked when an exception escapes out of the exception notification
return -1;
}
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
-// This method will return a BOOL indicating if the delegate should be invoked for the exception
-// of the specified corruption severity.
-BOOL ExceptionNotifications::CanDelegateBeInvokedForException(OBJECTREF *pDelegate, CorruptionSeverity severity)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(pDelegate != NULL && IsProtectedByGCFrame(pDelegate) && (*pDelegate != NULL));
- PRECONDITION(severity > NotSet);
- }
- CONTRACTL_END;
-
- // Notifications for CSE are only delivered if the delegate target follows CSE rules.
- BOOL fCanMethodHandleException = g_pConfig->LegacyCorruptedStateExceptionsPolicy() ? TRUE:(severity == NotCorrupting);
- if (!fCanMethodHandleException)
- {
- EX_TRY
- {
- // Get the MethodDesc of the delegate to be invoked
- MethodDesc *pMDDelegate = COMDelegate::GetMethodDesc(*pDelegate);
- _ASSERTE(pMDDelegate != NULL);
-
- // Check the callback target and see if it is following CSE rules or not.
- fCanMethodHandleException = CEHelper::CanMethodHandleException(severity, pMDDelegate);
- }
- EX_CATCH
- {
- // Incase of any exceptions, pretend we cannot handle the exception
- fCanMethodHandleException = FALSE;
- LOG((LF_EH, LL_INFO100, "ExceptionNotifications::CanDelegateBeInvokedForException: Exception while trying to determine if exception notification can be invoked or not.\n"));
- }
- EX_END_CATCH(RethrowCorruptingExceptions); // Dont swallow any CSEs.
- }
-
- return fCanMethodHandleException;
-}
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
-
-// This method will make the actual delegate invocation for the exception notification to be delivered. If an
-// exception escapes out of the notification, our filter in ExceptionNotifications::DeliverNotification will
-// address it.
-void ExceptionNotifications::InvokeNotificationDelegate(ExceptionNotificationHandlerType notificationType, OBJECTREF *pDelegate, OBJECTREF *pEventArgs,
- OBJECTREF *pAppDomain
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- , CorruptionSeverity severity
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
- )
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(pDelegate != NULL && IsProtectedByGCFrame(pDelegate) && (*pDelegate != NULL));
- PRECONDITION(pEventArgs != NULL && IsProtectedByGCFrame(pEventArgs));
- PRECONDITION(pAppDomain != NULL && IsProtectedByGCFrame(pAppDomain));
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- PRECONDITION(severity > NotSet);
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
- // Unhandled Exception Notification is delivered via Unhandled Exception Processing
- // mechanism.
- PRECONDITION(notificationType != UnhandledExceptionHandler);
- }
- CONTRACTL_END;
-
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- // Notifications are delivered based upon corruption severity of the exception
- if (!ExceptionNotifications::CanDelegateBeInvokedForException(pDelegate, severity))
- {
- LOG((LF_EH, LL_INFO100, "ExceptionNotifications::InvokeNotificationDelegate: Delegate cannot be invoked for corruption severity %d\n",
- severity));
- return;
- }
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
-
- // We've already exercised the prestub on this delegate's COMDelegate::GetMethodDesc,
- // as part of wiring up a reliable event sink in the BCL. Deliver the notification.
- ExceptionNotifications::DeliverExceptionNotification(notificationType, pDelegate, pAppDomain, pEventArgs);
-}
-
// This method returns a BOOL to indicate if the AppDomain is ready to receive exception notifications or not.
BOOL ExceptionNotifications::CanDeliverNotificationToCurrentAppDomain(ExceptionNotificationHandlerType notificationType)
{
// so that if an exception escapes out of the notification callback, we will trigger failfast from
// our filter.
void ExceptionNotifications::DeliverNotification(ExceptionNotificationHandlerType notificationType,
- OBJECTREF *pThrowable
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- , CorruptionSeverity severity
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
- )
+ OBJECTREF *pThrowable)
{
STATIC_CONTRACT_GC_TRIGGERS;
STATIC_CONTRACT_NOTHROW; // NOTHROW because incase of an exception, we will FailFast.
{
ExceptionNotificationHandlerType notificationType;
OBJECTREF *pThrowable;
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- CorruptionSeverity severity;
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
} args;
args.notificationType = notificationType;
args.pThrowable = pThrowable;
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- args.severity = severity;
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
PAL_TRY(TryArgs *, pArgs, &args)
{
// Make the call to the actual method that will invoke the callbacks
ExceptionNotifications::DeliverNotificationInternal(pArgs->notificationType,
- pArgs->pThrowable
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- , pArgs->severity
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
- );
+ pArgs->pThrowable);
}
PAL_EXCEPT_FILTER(ExceptionNotificationFilter)
{
// This method will deliver the exception notification to the current AppDomain.
void ExceptionNotifications::DeliverNotificationInternal(ExceptionNotificationHandlerType notificationType,
- OBJECTREF *pThrowable
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- , CorruptionSeverity severity
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
- )
+ OBJECTREF *pThrowable)
{
CONTRACTL
{
PRECONDITION(notificationType != UnhandledExceptionHandler);
PRECONDITION((pThrowable != NULL) && (*pThrowable != NULL));
PRECONDITION(ExceptionNotifications::CanDeliverNotificationToCurrentAppDomain(notificationType));
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- PRECONDITION(severity > NotSet); // Exception corruption severity must be valid at this point.
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
}
CONTRACTL_END;
gc.arrDelegates = (PTRARRAYREF) ((DELEGATEREF)(gc.oNotificationDelegate))->GetInvocationList();
if (gc.arrDelegates == NULL || !gc.arrDelegates->GetMethodTable()->IsArray())
{
- ExceptionNotifications::InvokeNotificationDelegate(notificationType, &gc.oNotificationDelegate, &gc.oEventArgs,
- &gc.oCurAppDomain
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- , severity
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
- );
+ ExceptionNotifications::DeliverExceptionNotification(notificationType, &gc.oNotificationDelegate, &gc.oCurAppDomain, &gc.oEventArgs);
}
else
{
for (UINT_PTR i=0; i<cnt; i++)
{
gc.oInnerDelegate = gc.arrDelegates->m_Array[i];
- ExceptionNotifications::InvokeNotificationDelegate(notificationType, &gc.oInnerDelegate, &gc.oEventArgs,
- &gc.oCurAppDomain
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- , severity
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
- );
+ ExceptionNotifications::DeliverExceptionNotification(notificationType, &gc.oInnerDelegate, &gc.oCurAppDomain, &gc.oEventArgs);
}
}
}
oThrowable = pCurTES->GetThrowable();
_ASSERTE(oThrowable != NULL);
- ExceptionNotifications::DeliverNotification(FirstChanceExceptionHandler, &oThrowable
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- , pCurTES->GetCurrentExceptionTracker()->GetCorruptionSeverity()
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
- );
+ ExceptionNotifications::DeliverNotification(FirstChanceExceptionHandler, &oThrowable);
GCPROTECT_END();
}
BOOL IsIPinVirtualStub(PCODE f_IP);
bool IsIPInMarkedJitHelper(UINT_PTR uControlPc);
+BOOL IsProcessCorruptedStateException(DWORD dwExceptionCode, OBJECTREF throwable);
+
BOOL AdjustContextForJITHelpers(EXCEPTION_RECORD *pExceptionRecord, CONTEXT *pContext);
#if defined(FEATURE_HIJACK) && (!defined(TARGET_X86) || defined(TARGET_UNIX))
void * pPrevExceptionRecord;
#endif
- // Is the current exception a longjmp?
- CORRUPTING_EXCEPTIONS_ONLY(BOOL m_fIsLongJump;)
void Init()
{
LIMITED_METHOD_CONTRACT;
pCurrentExceptionRecord = 0;
pPrevExceptionRecord = 0;
#endif
- // By default, the current exception is not a longjmp
- CORRUPTING_EXCEPTIONS_ONLY(m_fIsLongJump = FALSE;)
}
};
// Throw an object.
//==========================================================================
-VOID DECLSPEC_NORETURN RealCOMPlusThrow(OBJECTREF throwable
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- , CorruptionSeverity severity = NotCorrupting
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
- );
+VOID DECLSPEC_NORETURN RealCOMPlusThrow(OBJECTREF throwable);
//==========================================================================
// Throw an undecorated runtime exception.
EXCEPTION_POINTERS *pExceptionInfo, // the pExceptionInfo passed to a filter function.
PVOID pParam);
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
-// -----------------------------------------------------------------------
-// Support for Corrupted State Exceptions
-// -----------------------------------------------------------------------
-#ifndef HANDLE_PROCESS_CORRUPTED_STATE_EXCEPTION_ATTRIBUTE
-#define HANDLE_PROCESS_CORRUPTED_STATE_EXCEPTION_ATTRIBUTE "System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptionsAttribute"
-#endif // HANDLE_PROCESS_CORRUPTED_STATE_EXCEPTION_ATTRIBUTE
-
-#ifndef HIGHEST_MAJOR_VERSION_OF_PREV4_RUNTIME
-#define HIGHEST_MAJOR_VERSION_OF_PREV4_RUNTIME 2
-#endif // HIGHEST_MAJOR_VERSION_OF_PREV4_RUNTIME
-
-// This helper class contains static method to support working with Corrupted State Exceptions,
-// including checking if a method can handle it or not, copy state across throwables, etc.
-class CEHelper
-{
- BOOL static IsMethodInPreV4Assembly(PTR_MethodDesc pMethodDesc);
- BOOL static CanMethodHandleCE(PTR_MethodDesc pMethodDesc, CorruptionSeverity severity);
-
-public:
- BOOL static CanMethodHandleException(CorruptionSeverity severity, PTR_MethodDesc pMethodDesc);
- BOOL static CanIDispatchTargetHandleException();
- BOOL static IsProcessCorruptedStateException(DWORD dwExceptionCode, BOOL fCheckForSO = TRUE);
- BOOL static IsProcessCorruptedStateException(OBJECTREF oThrowable);
- BOOL static IsLastActiveExceptionCorrupting(BOOL fMarkForReuseIfCorrupting = FALSE);
- BOOL static ShouldTreatActiveExceptionAsNonCorrupting();
- void static MarkLastActiveExceptionCorruptionSeverityForReraiseReuse();
- void static SetupCorruptionSeverityForActiveException(BOOL fIsRethrownException, BOOL fIsNestedException, BOOL fShouldTreatExceptionAsNonCorrupting = FALSE);
-#ifdef FEATURE_EH_FUNCLETS
- typedef DPTR(class ExceptionTracker) PTR_ExceptionTracker;
- void static SetupCorruptionSeverityForActiveExceptionInUnwindPass(Thread *pCurThread, PTR_ExceptionTracker pEHTracker, BOOL fIsFirstPass,
- DWORD dwExceptionCode);
-#endif // FEATURE_EH_FUNCLETS
- void static ResetLastActiveCorruptionSeverityPostCatchHandler(Thread *pThread);
-};
-
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
-
#ifndef DACCESS_COMPILE
// exception filter invoked for unhandled exceptions on the entry point thread (thread 0)
LONG EntryPointFilter(PEXCEPTION_POINTERS pExceptionInfo, PVOID _pData);
OBJECTREF *pOutEventArgs, OBJECTREF *pThrowable);
void static DeliverNotificationInternal(ExceptionNotificationHandlerType notificationType,
- OBJECTREF *pThrowable
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- , CorruptionSeverity severity
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
- );
-
- void static InvokeNotificationDelegate(ExceptionNotificationHandlerType notificationType, OBJECTREF *pDelegate, OBJECTREF *pEventArgs,
- OBJECTREF *pAppDomain
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- , CorruptionSeverity severity
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
- );
+ OBJECTREF *pThrowable);
public:
- BOOL static CanDeliverNotificationToCurrentAppDomain(ExceptionNotificationHandlerType notificationType);
+ void static DeliverExceptionNotification(ExceptionNotificationHandlerType notificationType, OBJECTREF *pDelegate, OBJECTREF *pEventArgs,
+ OBJECTREF *pAppDomain);
- void static DeliverNotification(ExceptionNotificationHandlerType notificationType,
- OBJECTREF *pThrowable
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- , CorruptionSeverity severity
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
- );
+ BOOL static CanDeliverNotificationToCurrentAppDomain(ExceptionNotificationHandlerType notificationType);
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- BOOL static CanDelegateBeInvokedForException(OBJECTREF *pDelegate, CorruptionSeverity severity);
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
+ void static DeliverNotification(ExceptionNotificationHandlerType notificationType, OBJECTREF *pThrowable);
public:
- void static DeliverExceptionNotification(ExceptionNotificationHandlerType notificationType, OBJECTREF *pDelegate,
- OBJECTREF *pAppDomain, OBJECTREF *pEventArgs);
void static DeliverFirstChanceNotification();
};
!(dwExceptionFlags & EXCEPTION_UNWINDING),
&STState);
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- // Only setup the Corruption Severity in the first pass
if (!(dwExceptionFlags & EXCEPTION_UNWINDING))
{
// Switch to COOP mode
GCX_COOP();
- if (pTracker && pTracker->GetThrowable() != NULL)
- {
- // Setup the state in current exception tracker indicating the corruption severity
- // of the active exception.
- CEHelper::SetupCorruptionSeverityForActiveException((STState == ExceptionTracker::STS_FirstRethrowFrame), (pTracker->GetPreviousExceptionTracker() != NULL),
- CEHelper::ShouldTreatActiveExceptionAsNonCorrupting());
- }
-
// Failfast if exception indicates corrupted process state
- if (pTracker->GetCorruptionSeverity() == ProcessCorrupting)
+ if (IsProcessCorruptedStateException(pExceptionRecord->ExceptionCode, pTracker->GetThrowable()))
{
OBJECTREF oThrowable = NULL;
SString message;
EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE(pExceptionRecord->ExceptionCode, (LPCWSTR)message);
}
}
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
#ifndef TARGET_UNIX // Watson is on Windows only
// Setup bucketing details for nested exceptions (rethrow and non-rethrow) only if we are in the first pass
if (fIsILStub && !fIsFunclet) // only make this callback on the main method body of IL stubs
pUserMDForILStub = GetUserMethodForILStub(pThread, sf.SP, pMD, &pILStubFrame);
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- BOOL fCanMethodHandleException = TRUE;
- CorruptionSeverity currentSeverity = NotCorrupting;
- {
- // Switch to COOP mode since we are going to request throwable
- GCX_COOP();
-
- // We must defer to the MethodDesc of the user method instead of the IL stub
- // itself because the user can specify the policy on a per-method basis and
- // that won't be reflected via the IL stub's MethodDesc.
- MethodDesc * pMDWithCEAttribute = (pUserMDForILStub != NULL) ? pUserMDForILStub : pMD;
-
- // Check if the exception can be delivered to the method? It will check if the exception
- // is a CE or not. If it is, it will check if the method can process it or not.
- currentSeverity = pThread->GetExceptionState()->GetCurrentExceptionTracker()->GetCorruptionSeverity();
- fCanMethodHandleException = CEHelper::CanMethodHandleException(currentSeverity, pMDWithCEAttribute);
- }
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
-
// Doing rude abort. Skip all non-constrained execution region code.
// When rude abort is initiated, we cannot intercept any exceptions.
if (pThread->IsRudeAbortInitiated())
const METHODTOKEN& MethToken = pcfThisFrame->GetMethodToken();
EH_CLAUSE_ENUMERATOR EnumState;
- unsigned EHCount;
-
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- // The method cannot handle the exception (e.g. cannot handle the CE), then simply bail out
- // without examining the EH clauses in it.
- if (!fCanMethodHandleException)
- {
- LOG((LF_EH, LL_INFO100, "ProcessManagedCallFrame - CEHelper decided not to look for exception handlers in the method(MD:%p).\n", pMD));
-
- // Set the flag to skip this frame since the CE cannot be delivered
- _ASSERTE(currentSeverity == ProcessCorrupting);
-
- // Force EHClause count to be zero
- EHCount = 0;
- }
- else
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
- {
- EHCount = pJitMan->InitializeEHEnumeration(MethToken, &EnumState);
- }
-
+ unsigned EHCount = pJitMan->InitializeEHEnumeration(MethToken, &EnumState);
if (!fIsFirstPass)
{
}
}
}
-
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- if (fCreateNewTracker)
- {
- // Exception tracker should be in the 2nd pass right now
- _ASSERTE(!pTracker->IsInFirstPass());
-
- // The corruption severity of a newly created tracker is NotSet
- _ASSERTE(pTracker->GetCorruptionSeverity() == NotSet);
-
- // See comment in CEHelper::SetupCorruptionSeverityForActiveExceptionInUnwindPass for details
- CEHelper::SetupCorruptionSeverityForActiveExceptionInUnwindPass(pThread, pTracker, FALSE, pExceptionRecord->ExceptionCode);
- }
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
}
_ASSERTE(pTracker->m_pLimitFrame >= pThread->GetFrame());
ThreadExceptionState * pCurTES = pCurThread->GetExceptionState();
_ASSERTE(pCurTES != NULL);
-
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- ExceptionTracker* pEHTracker = pCurTES->GetCurrentExceptionTracker();
- if (pEHTracker == NULL)
- {
- CorruptionSeverity severity = NotCorrupting;
- if (CEHelper::IsProcessCorruptedStateException(ex.GetExceptionRecord()->ExceptionCode))
- {
- severity = ProcessCorrupting;
- }
-
- pCurTES->SetLastActiveExceptionCorruptionSeverity(severity);
- }
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
}
throw std::move(ex);
m_WatsonBucketTracker.Init();
#endif // !TARGET_UNIX
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- // Initialize the default exception severity to NotCorrupting
- m_CorruptionSeverity = NotSet;
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
-
// By default, mark the tracker as not having delivered the first
// chance exception notification
m_fDeliveredFirstChanceNotification = FALSE;
m_WatsonBucketTracker.Init();
#endif // !TARGET_UNIX
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- // Initialize the default exception severity to NotCorrupting
- m_CorruptionSeverity = NotSet;
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
-
// By default, mark the tracker as not having delivered the first
// chance exception notification
m_fDeliveredFirstChanceNotification = FALSE;
}
#endif // !TARGET_UNIX
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
-private:
- CorruptionSeverity m_CorruptionSeverity;
-public:
- inline CorruptionSeverity GetCorruptionSeverity()
- {
- LIMITED_METHOD_CONTRACT;
-
- return (CorruptionSeverity)GET_CORRUPTION_SEVERITY(m_CorruptionSeverity);
- }
-
- inline void SetCorruptionSeverity(CorruptionSeverity severityToSet)
- {
- LIMITED_METHOD_CONTRACT;
-
- m_CorruptionSeverity = severityToSet;
- }
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
-
private:
BOOL m_fDeliveredFirstChanceNotification;
// Actual UEF worker prototype for use by GCUnhandledExceptionFilter.
extern LONG InternalUnhandledExceptionFilter_Worker(PEXCEPTION_POINTERS pExceptionInfo);
-//==========================================================================
-// Installs a handler to unwind exception frames, but not catch the exception
-//==========================================================================
-
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
-// -----------------------------------------------------------------------
-// Support for Corrupted State Exceptions
-// -----------------------------------------------------------------------
-// This enumeration defines the corruption severity of an exception and
-// whether it should be reused for the next exception thrown or not.
-enum CorruptionSeverity
-{
- UseLast = 0x0, // When specified, the last active corruption severity from TES should be used
- NotSet = 0x1, // Corruption Severity has not been set - this is the default/reset value
- NotCorrupting = 0x2, // Indicates exception is not corrupting
- ProcessCorrupting = 0x4, // Indicates exception represents process corrupted state
- ReuseForReraise = 0x2000 // Indicates that the corruption severity should be reused for the next exception thrown,
- // provided its not nested and isnt a rethrow. This flag is used typically for propagation of
- // severity across boundaries like Reflection invocation, AD transition etc.
-};
-
-#define GET_CORRUPTION_SEVERITY(severity) (((severity) & (~ReuseForReraise)))
-#define CAN_REUSE_CORRUPTION_SEVERITY(severity) (((severity) & ReuseForReraise) == ReuseForReraise)
-
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
-
-VOID DECLSPEC_NORETURN RaiseTheException(OBJECTREF throwable, BOOL rethrow
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- , CorruptionSeverity severity
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
-);
-
VOID DECLSPEC_NORETURN RaiseTheExceptionInternalOnly(OBJECTREF throwable, BOOL rethrow, BOOL fForStackOverflow = FALSE);
#if defined(DACCESS_COMPILE) || defined(CROSSGEN_COMPILE)
DestroyExceptionHandle();
m_hThrowable = NULL;
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- // Initialize the default exception severity to NotCorrupting
- m_CorruptionSeverity = NotSet;
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
-
// By default, mark the tracker as not having delivered the first
// chance exception notification
m_fDeliveredFirstChanceNotification = FALSE;
}
#endif
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
-private:
- CorruptionSeverity m_CorruptionSeverity;
-public:
- inline CorruptionSeverity GetCorruptionSeverity()
- {
- LIMITED_METHOD_CONTRACT;
-
- return (CorruptionSeverity)GET_CORRUPTION_SEVERITY(m_CorruptionSeverity);
- }
-
- inline void SetCorruptionSeverity(CorruptionSeverity severityToSet)
- {
- LIMITED_METHOD_CONTRACT;
-
- m_CorruptionSeverity = severityToSet;
- }
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
-
private:
BOOL m_fDeliveredFirstChanceNotification;
public:
// Init the UE Watson BucketTracker
m_UEWatsonBucketTracker.Init();
#endif // !TARGET_UNIX
-
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- // Initialize the default exception severity to NotCorrupting
- m_LastActiveExceptionCorruptionSeverity = NotSet;
- m_fCanReflectionTargetHandleException = FALSE;
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
-
}
ThreadExceptionState::~ThreadExceptionState()
}
#endif
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
-private:
- CorruptionSeverity m_LastActiveExceptionCorruptionSeverity;
- BOOL m_fCanReflectionTargetHandleException;
-
-public:
- // Returns the corruption severity of the last active exception
- inline CorruptionSeverity GetLastActiveExceptionCorruptionSeverity()
- {
- LIMITED_METHOD_CONTRACT;
-
- return (CorruptionSeverity)GET_CORRUPTION_SEVERITY(m_LastActiveExceptionCorruptionSeverity);
- }
-
- // Set the corruption severity of the last active exception
- inline void SetLastActiveExceptionCorruptionSeverity(CorruptionSeverity severityToSet)
- {
- LIMITED_METHOD_CONTRACT;
-
- m_LastActiveExceptionCorruptionSeverity = severityToSet;
- }
-
- // Returns a bool indicating if the last active exception's corruption severity should
- // be used when exception is reraised (e.g. Reflection Invocation, AD transition, etc)
- inline BOOL ShouldLastActiveExceptionCorruptionSeverityBeReused()
- {
- LIMITED_METHOD_CONTRACT;
-
- return CAN_REUSE_CORRUPTION_SEVERITY(m_LastActiveExceptionCorruptionSeverity);
- }
-
- // Returns a BOOL to indicate if reflection target can handle CSE or not.
- // This is used in DispatchInfo::CanIDispatchTargetHandleException.
- inline BOOL CanReflectionTargetHandleException()
- {
- LIMITED_METHOD_CONTRACT;
-
- return m_fCanReflectionTargetHandleException;
- }
-
- // Sets a BOOL indicate if the Reflection invocation target can handle exception or not.
- // Used in ReflectionInvocation.cpp.
- inline void SetCanReflectionTargetHandleException(BOOL fCanReflectionTargetHandleException)
- {
- LIMITED_METHOD_CONTRACT;
-
- m_fCanReflectionTargetHandleException = fCanReflectionTargetHandleException;
- }
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
-
private:
ThreadExceptionFlag m_flag;
friend class StackFrameIterator;
friend class TailCallFrame;
friend class AppDomain;
- friend VOID RealCOMPlusThrow(OBJECTREF
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- , CorruptionSeverity severity
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
- );
+ friend VOID RealCOMPlusThrow(OBJECTREF);
friend FCDECL0(VOID, JIT_StressGC);
#ifdef _DEBUG
friend LONG WINAPI CLRVectoredExceptionHandlerShim(PEXCEPTION_POINTERS pExceptionInfo);
GCPROTECT_BEGIN(throwable);
throwable = pThread->GetThrowable();
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
+ if (IsProcessCorruptedStateException(exceptionCode, throwable))
{
- // Setup the state in current exception tracker indicating the corruption severity
- // of the active exception.
- CEHelper::SetupCorruptionSeverityForActiveException(bRethrownException, bNestedException,
- CEHelper::ShouldTreatActiveExceptionAsNonCorrupting());
-
// Failfast if exception indicates corrupted process state
- if (pExInfo->GetCorruptionSeverity() == ProcessCorrupting)
- EEPOLICY_HANDLE_FATAL_ERROR(exceptionCode);
+ EEPOLICY_HANDLE_FATAL_ERROR(exceptionCode);
}
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
// If we're out of memory, then we figure there's probably not memory to maintain a stack trace, so we skip it.
// If we've got a stack overflow, then we figure the stack will be so huge as to make tracking the stack trace
tct.pTopFrame = GetCurrFrame(pEstablisherFrame); // highest frame to search to
tct.pBottomFrame = NULL;
- // Set the flag indicating if the current exception represents a longjmp.
- // See comment in COMPlusUnwindCallback for details.
- CORRUPTING_EXCEPTIONS_ONLY(tct.m_fIsLongJump = (exceptionCode == STATUS_LONGJUMP);)
-
#ifdef _DEBUG
tct.pCurrentExceptionRecord = pEstablisherFrame;
tct.pPrevExceptionRecord = GetPrevSEHRecord(pEstablisherFrame);
if (fIsILStub)
pUserMDForILStub = GetUserMethodForILStub(pThread, currentSP, pFunc, &pILStubFrame);
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- CorruptionSeverity currentSeverity = pThread->GetExceptionState()->GetCurrentExceptionTracker()->GetCorruptionSeverity();
- {
- // We must defer to the MethodDesc of the user method instead of the IL stub
- // itself because the user can specify the policy on a per-method basis and
- // that won't be reflected via the IL stub's MethodDesc.
- MethodDesc * pMDWithCEAttribute = fIsILStub ? pUserMDForILStub : pFunc;
-
- // Check if the exception can be delivered to the method? It will check if the exception
- // is a CE or not. If it is, it will check if the method can process it or not.
- fMethodCanHandleException = CEHelper::CanMethodHandleException(currentSeverity, pMDWithCEAttribute);
- }
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
-
// Let the profiler know that we are searching for a handler within this function instance
if (fGiveDebuggerAndProfilerNotification)
EEToProfilerExceptionInterfaceWrapper::ExceptionSearchFunctionEnter(pFunc);
ExceptionNotifications::DeliverFirstChanceNotification();
}
}
+
IJitManager* pJitManager = pCf->GetJitManager();
_ASSERTE(pJitManager);
- EH_CLAUSE_ENUMERATOR pEnumState;
- unsigned EHCount = 0;
-
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- // If exception cannot be handled, then just bail out. We shouldnt examine the EH clauses
- // in such a method.
- if (!fMethodCanHandleException)
- {
- LOG((LF_EH, LL_INFO100, "COMPlusThrowCallback - CEHelper decided not to look for exception handlers in the method(MD:%p).\n", pFunc));
- // Set the flag to skip this frame since the CE cannot be delivered
- _ASSERTE(currentSeverity == ProcessCorrupting);
-
- // Ensure EHClause count is zero
- EHCount = 0;
- }
- else
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
- {
- EHCount = pJitManager->InitializeEHEnumeration(pCf->GetMethodToken(), &pEnumState);
- }
+ EH_CLAUSE_ENUMERATOR pEnumState;
+ unsigned EHCount = pJitManager->InitializeEHEnumeration(pCf->GetMethodToken(), &pEnumState);
if (EHCount == 0)
{
TypeHandle thrownType = TypeHandle();
- BOOL fCanMethodHandleException = TRUE;
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- // MethodDesc's security information (i.e. whether it is critical or transparent) is calculated lazily.
- // If this method's security information was not precalculated, then it would have been in the first pass
- // already using Security::IsMethodCritical which could take have taken us down a path which is GC_TRIGGERS.
- //
- //
- // However, this unwind callback (for X86) is GC_NOTRIGGER and at this point the security information would have been
- // calculated already. Hence, we wouldnt endup in the GC_TRIGGERS path. Thus, to keep SCAN.EXE (static contract analyzer) happy,
- // we will pass a FALSE to the CanMethodHandleException call, indicating we dont need to calculate security information (and thus,
- // not go down the GC_TRIGGERS path.
- //
- // Check if the exception can be delivered to the method? It will check if the exception
- // is a CE or not. If it is, it will check if the method can process it or not.
- CorruptionSeverity currentSeverity = pThread->GetExceptionState()->GetCurrentExceptionTracker()->GetCorruptionSeverity();
-
- // We have to do this check for x86 since, unlike 64bit which will setup a new exception tracker for longjmp,
- // x86 only sets up new trackers in the first pass (and longjmp is 2nd pass only exception). Hence, we pass
- // this information in the callback structure without affecting any existing exception tracker (incase longjmp was
- // a nested exception).
- if (pData->m_fIsLongJump)
- {
- // Longjump is not a CSE. With a CSE in progress, this can be invoked by either:
- //
- // 1) Managed code (e.g. finally/fault/catch), OR
- // 2) By native code
- //
- // In scenario (1), managed code can invoke it only if it was attributed with HPCSE attribute. Thus,
- // longjmp is no different than managed code doing a "throw new Exception();".
- //
- // In scenario (2), longjmp is no different than any other non-CSE native exception raised.
- //
- // In both these case, longjmp should be treated as non-CSE. Since x86 does not setup a tracker for
- // it (see comment above), we pass this information (of whether the current exception is a longjmp or not)
- // to this callback (from UnwindFrames) to setup the correct corruption severity.
- //
- // http://www.nynaeve.net/?p=105 has a brief description of how exception-safe setjmp/longjmp works.
- currentSeverity = NotCorrupting;
- }
- {
- MethodDesc * pFuncWithCEAttribute = pFunc;
- Frame * pILStubFrame = NULL;
- if (pFunc->IsILStub())
- {
- // We must defer to the MethodDesc of the user method instead of the IL stub
- // itself because the user can specify the policy on a per-method basis and
- // that won't be reflected via the IL stub's MethodDesc.
- pFuncWithCEAttribute = GetUserMethodForILStub(pThread, (UINT_PTR)pStack, pFunc, &pILStubFrame);
- }
- fCanMethodHandleException = CEHelper::CanMethodHandleException(currentSeverity, pFuncWithCEAttribute);
- }
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
-
#ifdef DEBUGGING_SUPPORTED
LOG((LF_EH, LL_INFO1000, "COMPlusUnwindCallback: Intercept %d, pData->pFunc 0x%X, pFunc 0x%X, pData->pStack 0x%X, pStack 0x%X\n",
pExInfo->m_ExceptionFlags.DebuggerInterceptInfo(),
EEToProfilerExceptionInterfaceWrapper::ExceptionUnwindFunctionEnter(pFunc);
EH_CLAUSE_ENUMERATOR pEnumState;
- unsigned EHCount;
-
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- if (!fCanMethodHandleException)
- {
- LOG((LF_EH, LL_INFO100, "COMPlusUnwindCallback - CEHelper decided not to look for exception handlers in the method(MD:%p).\n", pFunc));
-
- // Set the flag to skip this frame since the CE cannot be delivered
- _ASSERTE(currentSeverity == ProcessCorrupting);
-
- // Force EHClause count to be zero
- EHCount = 0;
- }
- else
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
- {
- EHCount = pJitManager->InitializeEHEnumeration(pCf->GetMethodToken(), &pEnumState);
- }
+ unsigned EHCount = pJitManager->InitializeEHEnumeration(pCf->GetMethodToken(), &pEnumState);
if (EHCount == 0)
{
//--------------------------------------------------------------------------------
// IUnknown *GetComIPFromObjectRef(OBJECTREF *poref, MethodTable *pMT, ...)
// Convert ObjectRef to a COM IP, based on MethodTable* pMT.
-IUnknown *GetComIPFromObjectRef(OBJECTREF *poref, MethodTable *pMT, BOOL bSecurityCheck, BOOL bEnableCustomizedQueryInterface)
+IUnknown *GetComIPFromObjectRef(OBJECTREF *poref, MethodTable *pMT, BOOL bEnableCustomizedQueryInterface)
{
CONTRACT (IUnknown*)
{
CCWHolder pCCWHold = ComCallWrapper::InlineGetWrapper(poref);
GetComIPFromCCW::flags flags = GetComIPFromCCW::None;
- if (!bSecurityCheck) { flags |= GetComIPFromCCW::SuppressSecurityCheck; }
if (!bEnableCustomizedQueryInterface) { flags |= GetComIPFromCCW::SuppressCustomizedQueryInterface; }
pUnk = ComCallWrapper::GetComIPFromCCW(pCCWHold, GUID_NULL, pMT, flags);
//--------------------------------------------------------------------------------
// IUnknown *GetComIPFromObjectRef(OBJECTREF *poref, MethodTable *pMT, ...);
// Convert ObjectRef to a COM IP, based on MethodTable* pMT.
-IUnknown *GetComIPFromObjectRef(OBJECTREF *poref, MethodTable *pMT, BOOL bSecurityCheck = TRUE, BOOL bEnableCustomizedQueryInterface = TRUE);
+IUnknown *GetComIPFromObjectRef(OBJECTREF *poref, MethodTable *pMT, BOOL bEnableCustomizedQueryInterface = TRUE);
//--------------------------------------------------------------------------------
}
}
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- if (!g_pConfig->LegacyCorruptedStateExceptionsPolicy())
- {
- // Within the VM, we could have thrown and caught a managed exception. This is done by
- // RaiseTheException that will flag that exception's corruption severity to be used
- // incase it leaks out to managed code.
- //
- // If it does not leak out, but ends up calling into managed code that throws,
- // we will come here. In such a case, simply reset the corruption-severity
- // since we want the exception being thrown to have its correct severity set
- // when CLR's managed code exception handler sets it.
-
- ThreadExceptionState *pExState = GetThread()->GetExceptionState();
- pExState->SetLastActiveExceptionCorruptionSeverity(NotSet);
- }
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
-
RaiseTheExceptionInternalOnly(oref, FALSE);
HELPER_METHOD_FRAME_END();
HRESULT m_hrResultCode;
LOADERHANDLE m_hInitException;
PTR_LoaderAllocator m_pLoaderAllocator;
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- // Field to maintain the corruption severity of the exception
- CorruptionSeverity m_CorruptionSeverity;
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
ListLockEntryBase(List_t *pList, ELEMENT data, const char *description = NULL)
: m_deadlock(description),
m_hrResultCode(S_FALSE),
m_hInitException(NULL),
m_pLoaderAllocator(dac_cast<PTR_LoaderAllocator>(nullptr))
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- ,
- m_CorruptionSeverity(NotCorrupting)
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
{
WRAPPER_NO_CONTRACT;
}
if (fOnlyInContext && !IsObjectInContext(&oref))
retVal = NULL;
else
- retVal = GetComIPFromObjectRef(&oref, th.GetMethodTable(), TRUE, bEnableCustomizedQueryInterface);
+ retVal = GetComIPFromObjectRef(&oref, th.GetMethodTable(), bEnableCustomizedQueryInterface);
HELPER_METHOD_FRAME_END();
return retVal;
// a subclass of Error</TODO>
*pThrowable = GET_THROWABLE();
_ASSERTE(fRet == FALSE);
-
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- // If active thread state does not have a CorruptionSeverity set for the exception,
- // then set one up based upon the current exception code and/or the throwable.
- //
- // When can we be here and current exception tracker may not have corruption severity set?
- // Incase of SO in managed code, SO is never seen by CLR's exception handler for managed code
- // and if this happens in cctor, we can end up here without the corruption severity set.
- Thread *pThread = GetThread();
- _ASSERTE(pThread != NULL);
- ThreadExceptionState *pCurTES = pThread->GetExceptionState();
- _ASSERTE(pCurTES != NULL);
- if (pCurTES->GetLastActiveExceptionCorruptionSeverity() == NotSet)
- {
- if (CEHelper::IsProcessCorruptedStateException(GetCurrentExceptionCode()) ||
- CEHelper::IsProcessCorruptedStateException(*pThrowable))
- {
- // Process Corrupting
- pCurTES->SetLastActiveExceptionCorruptionSeverity(ProcessCorrupting);
- LOG((LF_EH, LL_INFO100, "MethodTable::RunClassInitEx - Exception treated as ProcessCorrupting.\n"));
- }
- else
- {
- // Not Corrupting
- pCurTES->SetLastActiveExceptionCorruptionSeverity(NotCorrupting);
- LOG((LF_EH, LL_INFO100, "MethodTable::RunClassInitEx - Exception treated as non-corrupting.\n"));
- }
- }
- else
- {
- LOG((LF_EH, LL_INFO100, "MethodTable::RunClassInitEx - Exception already has corruption severity set.\n"));
- }
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
}
EX_END_CATCH(SwallowAllExceptions)
((EXCEPTIONREF)(gc.pThrowable))->ClearStackTraceForThrow();
}
- // <FEATURE_CORRUPTING_EXCEPTIONS>
- // Specify the corruption severity to be used to raise this exception in COMPlusThrow below.
- // This will ensure that when the exception is seen by the managed code personality routine,
- // it will setup the correct corruption severity in the exception tracker.
- // </FEATURE_CORRUPTING_EXCEPTIONS>
-
- COMPlusThrow(gc.pThrowable
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- , pEntry->m_CorruptionSeverity
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
- );
+ COMPlusThrow(gc.pThrowable);
}
description = ".cctor lock";
pEntry->m_hrResultCode = E_FAIL;
SetClassInitError();
- #ifdef FEATURE_CORRUPTING_EXCEPTIONS
- // Save the corruption severity of the exception so that if the type system
- // attempts to pick it up from its cache list and throw again, it should
- // treat the exception as corrupting, if applicable.
- pEntry->m_CorruptionSeverity = pThread->GetExceptionState()->GetLastActiveExceptionCorruptionSeverity();
-
- // We should be having a valid corruption severity at this point
- _ASSERTE(pEntry->m_CorruptionSeverity != NotSet);
- #endif // FEATURE_CORRUPTING_EXCEPTIONS
-
- COMPlusThrow(gc.pThrowable
- #ifdef FEATURE_CORRUPTING_EXCEPTIONS
- , pEntry->m_CorruptionSeverity
- #endif // FEATURE_CORRUPTING_EXCEPTIONS
- );
+ COMPlusThrow(gc.pThrowable);
}
GCPROTECT_END();
{
hr = GET_EXCEPTION()->GetHR();
}
- EX_END_CATCH(RethrowCorruptingExceptions) // Make sure we crash on AV (instead of swallowing everything)
+ EX_END_CATCH(RethrowTerminalExceptions)
if (FAILED(hr))
{
}
#endif // _DEBUG && !TARGET_UNIX
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- // Get the corruption severity of the exception that came in through reflection invocation.
- CorruptionSeverity severity = GetThread()->GetExceptionState()->GetLastActiveExceptionCorruptionSeverity();
-
- // Since we are dealing with an exception, set the flag indicating if the target of Reflection can handle exception or not.
- // This flag is used in CEHelper::CanIDispatchTargetHandleException.
- GetThread()->GetExceptionState()->SetCanReflectionTargetHandleException(CEHelper::CanMethodHandleException(severity, pMethod));
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
-
OBJECTREF except = InvokeUtil::CreateTargetExcept(&targetException);
#ifndef TARGET_UNIX
// Since VM is throwing the exception, we set it to use the same corruption severity
// that the original exception came in with from reflection invocation.
- COMPlusThrow(except
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- , severity
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
- );
+ COMPlusThrow(except);
GCPROTECT_END();
}
ENDFORBIDGC();
}
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- // By default, set the flag in TES indicating the reflection target can handle CSE.
- // This flag is used in CEHelper::CanIDispatchTargetHandleException.
- pThread->GetExceptionState()->SetCanReflectionTargetHandleException(TRUE);
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
-
if (pValueClasses != NULL)
{
pProtectValueClassFrame = new (_alloca (sizeof (FrameWithCookie<ProtectValueClassFrame>)))
hr = pDispInfo->InvokeMember(pSimpleWrap, dispidMember, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, NULL, puArgErr);
}
- END_EXTERNAL_ENTRYPOINT_RETHROW_CORRUPTING_EXCEPTIONS; // This will ensure that entry points wont swallow CE and continue to let them propagate out.
+ END_EXTERNAL_ENTRYPOINT;
return hr;
}
// Syncup the LastThrownObject on the managed thread
SafeUpdateLastThrownObject();
}
-
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- // Since the catch clause has successfully executed and we are exiting it, reset the corruption severity
- // in the ThreadExceptionState for the last active exception. This will ensure that when the next exception
- // gets thrown/raised, EH tracker wont pick up an invalid value.
- if (!fIsDebuggerThread)
- {
- CEHelper::ResetLastActiveCorruptionSeverityPostCatchHandler(this);
- }
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
-
}
void Thread::SetLastThrownObjectHandle(OBJECTHANDLE h)