Skip to content

Commit 9495cbf

Browse files
Fix issue where variance checking uses an unsafe contract by being more strict in what we accept while verifying the type (#21)
1 parent a24bf8c commit 9495cbf

File tree

2 files changed

+20
-6
lines changed

2 files changed

+20
-6
lines changed

src/coreclr/vm/methodtable.cpp

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9189,7 +9189,7 @@ MethodDesc *MethodTable::GetDefaultConstructor(BOOL forceBoxedEntryPoint /* = FA
91899189
//==========================================================================================
91909190
// Finds the (non-unboxing) MethodDesc that implements the interface virtual static method pInterfaceMD.
91919191
MethodDesc *
9192-
MethodTable::ResolveVirtualStaticMethod(MethodTable* pInterfaceType, MethodDesc* pInterfaceMD, BOOL allowNullResult, BOOL checkDuplicates)
9192+
MethodTable::ResolveVirtualStaticMethod(MethodTable* pInterfaceType, MethodDesc* pInterfaceMD, BOOL allowNullResult, BOOL checkDuplicates, BOOL allowVariantMatches)
91939193
{
91949194
if (!pInterfaceMD->IsSharedByGenericMethodInstantiations() && !pInterfaceType->IsSharedByGenericInstantiations())
91959195
{
@@ -9225,7 +9225,7 @@ MethodTable::ResolveVirtualStaticMethod(MethodTable* pInterfaceType, MethodDesc*
92259225
return pMD;
92269226
}
92279227

9228-
if (pInterfaceType->HasVariance())
9228+
if (pInterfaceType->HasVariance() || pInterfaceType->HasTypeEquivalence())
92299229
{
92309230
// Variant interface dispatch
92319231
MethodTable::InterfaceMapIterator it = IterateInterfaceMap();
@@ -9240,12 +9240,26 @@ MethodTable::ResolveVirtualStaticMethod(MethodTable* pInterfaceType, MethodDesc*
92409240
if (!it.GetInterface()->HasSameTypeDefAs(pInterfaceType))
92419241
{
92429242
// Variance matches require a typedef match
9243+
// Equivalence isn't sufficient, and is uninteresting as equivalent interfaces cannot have static virtuals.
92439244
continue;
92449245
}
92459246

9246-
if (it.GetInterface()->CanCastTo(pInterfaceType, NULL))
9247+
BOOL equivalentOrVariantCompatible;
9248+
9249+
if (allowVariantMatches)
9250+
{
9251+
equivalentOrVariantCompatible = it.GetInterface()->CanCastTo(pInterfaceType, NULL);
9252+
}
9253+
else
9254+
{
9255+
// When performing override checking to ensure that a concrete type is valid, require the implementation
9256+
// actually implement the exact or equivalent interface.
9257+
equivalentOrVariantCompatible = it.GetInterface()->IsEquivalentTo(pInterfaceType, NULL);
9258+
}
9259+
9260+
if (equivalentOrVariantCompatible)
92479261
{
9248-
// Variant matching interface found
9262+
// Variant or equivalent matching interface found
92499263
// Attempt to resolve on variance matched interface
92509264
pMD = pMT->TryResolveVirtualStaticMethodOnThisType(it.GetInterface(), pInterfaceMD, checkDuplicates);
92519265
if (pMD != nullptr)
@@ -9406,7 +9420,7 @@ MethodTable::VerifyThatAllVirtualStaticMethodsAreImplemented()
94069420
MethodDesc *pMD = it.GetMethodDesc();
94079421
if (pMD->IsVirtual() &&
94089422
pMD->IsStatic() &&
9409-
!ResolveVirtualStaticMethod(pInterfaceMT, pMD, /* allowNullResult */ TRUE, /* checkDuplicates */ TRUE))
9423+
!ResolveVirtualStaticMethod(pInterfaceMT, pMD, /* allowNullResult */ TRUE, /* checkDuplicates */ TRUE, /* allowVariantMatches */ FALSE))
94109424
{
94119425
IMDInternalImport* pInternalImport = GetModule()->GetMDImport();
94129426
GetModule()->GetAssembly()->ThrowTypeLoadException(pInternalImport, GetCl(), pMD->GetName(), IDS_CLASSLOAD_STATICVIRTUAL_NOTIMPL);

src/coreclr/vm/methodtable.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2282,7 +2282,7 @@ class MethodTable
22822282

22832283

22842284
// Resolve virtual static interface method pInterfaceMD on this type.
2285-
MethodDesc *ResolveVirtualStaticMethod(MethodTable* pInterfaceType, MethodDesc* pInterfaceMD, BOOL allowNullResult, BOOL checkDuplicates = FALSE);
2285+
MethodDesc *ResolveVirtualStaticMethod(MethodTable* pInterfaceType, MethodDesc* pInterfaceMD, BOOL allowNullResult, BOOL checkDuplicates = FALSE, BOOL allowVariantMatches = TRUE);
22862286

22872287
// Try a partial resolve of the constraint call, up to generic code sharing.
22882288
//

0 commit comments

Comments
 (0)