diff options
author | Jarret Shook <jashoo@microsoft.com> | 2019-03-19 09:06:56 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-03-19 09:06:56 -0700 |
commit | 0786da806b9727c466f3f9393cb3d55cf9df7536 (patch) | |
tree | c9e15d565a726945a6bac065749b86f035caf903 /src/vm/comdelegate.cpp | |
parent | 1f3f474a13bdde1c5fecdf8cd9ce525dbe5df000 (diff) | |
download | coreclr-0786da806b9727c466f3f9393cb3d55cf9df7536.tar.gz coreclr-0786da806b9727c466f3f9393cb3d55cf9df7536.tar.bz2 coreclr-0786da806b9727c466f3f9393cb3d55cf9df7536.zip |
Revert "Delete suspicious code in delegate construction (#22830)" (#23291)
This reverts commit 674bdcbc2ac824d005b5179cee3c5826b582b9a6.
Diffstat (limited to 'src/vm/comdelegate.cpp')
-rw-r--r-- | src/vm/comdelegate.cpp | 78 |
1 files changed, 76 insertions, 2 deletions
diff --git a/src/vm/comdelegate.cpp b/src/vm/comdelegate.cpp index 9a131fa126..42f457ff3a 100644 --- a/src/vm/comdelegate.cpp +++ b/src/vm/comdelegate.cpp @@ -1626,9 +1626,35 @@ FCIMPL3(PCODE, COMDelegate::AdjustTarget, Object* refThisUNSAFE, Object* targetU // close delegates MethodTable* pMTTarg = target->GetMethodTable(); MethodTable* pMTMeth = pMeth->GetMethodTable(); + + BOOL isComObject = false; + +#ifdef FEATURE_COMINTEROP + isComObject = pMTTarg->IsComObjectType(); +#endif // FEATURE_COMINTEROP MethodDesc *pCorrectedMethod = pMeth; + if (pMTMeth != pMTTarg) + { + //They cast to an interface before creating the delegate, so we now need + //to figure out where this actually lives before we continue. + //<TODO>@perf: Grovelling with a signature is really slow. Speed this up.</TODO> + if (pCorrectedMethod->IsInterface()) + { + // No need to resolve the interface based method desc to a class based + // one for COM objects because we invoke directly thru the interface MT. + if (!isComObject) + { + // <TODO>it looks like we need to pass an ownerType in here. + // Why can we take a delegate to an interface method anyway? </TODO> + // + pCorrectedMethod = pMTTarg->FindDispatchSlotForInterfaceMD(pCorrectedMethod, TRUE /* throwOnConflict */).GetMethodDesc(); + _ASSERTE(pCorrectedMethod != NULL); + } + } + } + // Use the Unboxing stub for value class methods, since the value // class is constructed using the boxed instance. if (pCorrectedMethod->GetMethodTable()->IsValueType() && !pCorrectedMethod->IsUnboxingStub()) @@ -1772,6 +1798,53 @@ FCIMPL3(void, COMDelegate::DelegateConstruct, Object* refThisUNSAFE, Object* tar { if (pMTTarg) { + // We can skip the demand if SuppressUnmanagedCodePermission is present on the class, + // or in the case where we are setting up a delegate for a COM event sink + // we can skip the check if the source interface is defined in fully trusted code + // we can skip the check if the source interface is a disp-only interface + BOOL isComObject = false; +#ifdef FEATURE_COMINTEROP + isComObject = pMTTarg->IsComObjectType(); +#endif // FEATURE_COMINTEROP + + if (pMTMeth != pMTTarg) + { + // They cast to an interface before creating the delegate, so we now need + // to figure out where this actually lives before we continue. + // <TODO>@perf: We whould never be using this path to invoke on an interface - + // that should always be resolved when we are creating the delegate </TODO> + if (pMeth->IsInterface()) + { + // No need to resolve the interface based method desc to a class based + // one for COM objects because we invoke directly thru the interface MT. + if (!isComObject) + { + // <TODO>it looks like we need to pass an ownerType in here. + // Why can we take a delegate to an interface method anyway? </TODO> + // + MethodDesc * pDispatchSlotMD = pMTTarg->FindDispatchSlotForInterfaceMD(pMeth, TRUE /* throwOnConflict */).GetMethodDesc(); + if (pDispatchSlotMD == NULL) + { + COMPlusThrow(kArgumentException, W("Arg_DlgtTargMeth")); + } + + if (pMeth->HasMethodInstantiation()) + { + pMeth = MethodDesc::FindOrCreateAssociatedMethodDesc( + pDispatchSlotMD, + pMTTarg, + (!pDispatchSlotMD->IsStatic() && pMTTarg->IsValueType()), + pMeth->GetMethodInstantiation(), + FALSE /* allowInstParam */); + } + else + { + pMeth = pDispatchSlotMD; + } + } + } + } + g_IBCLogger.LogMethodTableAccess(pMTTarg); // Use the Unboxing stub for value class methods, since the value @@ -3157,9 +3230,10 @@ MethodDesc* COMDelegate::GetDelegateCtor(TypeHandle delegateType, MethodDesc *pT #endif // under the conditions below the delegate ctor needs to perform some heavy operation - // to get the unboxing stub + // to either resolve the interface call to the real target or to get the unboxing stub (or both) BOOL needsRuntimeInfo = !pTargetMethod->IsStatic() && - pTargetMethod->GetMethodTable()->IsValueType() && !pTargetMethod->IsUnboxingStub(); + (pTargetMethod->IsInterface() || + (pTargetMethod->GetMethodTable()->IsValueType() && !pTargetMethod->IsUnboxingStub())); if (needsRuntimeInfo) pRealCtor = MscorlibBinder::GetMethod(METHOD__MULTICAST_DELEGATE__CTOR_RT_CLOSED); |