Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix use-out-of-scope in signature comparison #88928

Merged
merged 5 commits into from
Jul 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/coreclr/vm/prestub.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1277,7 +1277,8 @@ namespace
continue;

// Check signature
MetaSig::CompareState state{};
TokenPairList list { nullptr };
MetaSig::CompareState state{ &list };
state.IgnoreCustomModifiers = ignoreCustomModifiers;
if (!DoesMethodMatchUnsafeAccessorDeclaration(cxt, curr, state))
continue;
Expand Down
28 changes: 17 additions & 11 deletions src/coreclr/vm/siginfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3662,7 +3662,8 @@ MetaSig::CompareElementType(
}
CONTRACTL_END

CompareState temp{};
TokenPairList tempList { nullptr };
CompareState temp{ &tempList };
if (state == NULL)
state = &temp;

Expand Down Expand Up @@ -3967,7 +3968,7 @@ MetaSig::CompareElementType(
argCnt1++;

TokenPairList newVisited = TokenPairList::AdjustForTypeEquivalenceForbiddenScope(state->Visited);
state->Visited = &newVisited;
*state->Visited = newVisited;

// Compare all parameters, incl. return parameter
while (argCnt1 > 0)
Expand Down Expand Up @@ -3998,7 +3999,7 @@ MetaSig::CompareElementType(
pSig1 - 1,
(DWORD)(pEndSig1 - pSig1) + 1);
TokenPairList newVisitedAlwaysForbidden = TokenPairList::AdjustForTypeEquivalenceForbiddenScope(state->Visited);
state->Visited = &newVisitedAlwaysForbidden;
*state->Visited = newVisitedAlwaysForbidden;

// Type constructors - The actual type is never permitted to participate in type equivalence.
if (!CompareElementType(
Expand All @@ -4024,7 +4025,7 @@ MetaSig::CompareElementType(
return FALSE;
}

state->Visited = &newVisited;
*state->Visited = newVisited;
while (argCnt1 > 0)
{
if (!CompareElementType(
Expand Down Expand Up @@ -4203,7 +4204,8 @@ MetaSig::CompareTypeDefsUnderSubstitutions(
SigPointer inst1 = pSubst1->GetInst();
SigPointer inst2 = pSubst2->GetInst();

CompareState state{ pVisited };
TokenPairList visited { pVisited };
CompareState state{ &visited };
for (DWORD i = 0; i < pTypeDef1->GetNumGenericArgs(); i++)
{
PCCOR_SIGNATURE startInst1 = inst1.GetPtr();
Expand Down Expand Up @@ -4409,6 +4411,8 @@ MetaSig::CompareMethodSigs(
IfFailThrow(CorSigUncompressData_EndPtr(pSig1, pEndSig1, &ArgCount1));
IfFailThrow(CorSigUncompressData_EndPtr(pSig2, pEndSig2, &ArgCount2));

TokenPairList visited{ pVisited };

if (ArgCount1 != ArgCount2)
{
if ((callConv & IMAGE_CEE_CS_CALLCONV_MASK) != IMAGE_CEE_CS_CALLCONV_VARARG)
Expand All @@ -4430,7 +4434,7 @@ MetaSig::CompareMethodSigs(
// to correctly handle overloads, where there are a number of varargs methods
// to pick from, like m1(int,...) and m2(int,int,...), etc.

CompareState state{ pVisited };
CompareState state{ &visited };
// <= because we want to include a check of the return value!
for (i = 0; i <= ArgCount1; i++)
{
Expand Down Expand Up @@ -4486,7 +4490,7 @@ MetaSig::CompareMethodSigs(
}

// do return type as well
CompareState state{ pVisited };
CompareState state{ &visited };
for (i = 0; i <= ArgCount1; i++)
{
if (i == 0 && skipReturnTypeSig)
Expand Down Expand Up @@ -4551,7 +4555,8 @@ BOOL MetaSig::CompareFieldSigs(
pEndSig1 = pSig1 + cSig1;
pEndSig2 = pSig2 + cSig2;

CompareState state{ pVisited };
TokenPairList visited { pVisited };
CompareState state{ &visited };
return(CompareElementType(++pSig1, ++pSig2, pEndSig1, pEndSig2, pModule1, pModule2, NULL, NULL, &state));
jkoritzinsky marked this conversation as resolved.
Show resolved Hide resolved
}

Expand Down Expand Up @@ -4865,11 +4870,12 @@ BOOL MetaSig::CompareVariableConstraints(const Substitution *pSubst1,
// because they
// a) are vacuous, and
// b) may be implicit (ie. absent) in the overridden variable's declaration
TokenPairList newVisited { nullptr };
if (!(CompareTypeDefOrRefOrSpec(pModule1, tkConstraintType1, NULL,
CoreLibBinder::GetModule(), g_pObjectClass->GetCl(), NULL, NULL) ||
CoreLibBinder::GetModule(), g_pObjectClass->GetCl(), NULL, &newVisited) ||
(((specialConstraints1 & gpNotNullableValueTypeConstraint) != 0) &&
(CompareTypeDefOrRefOrSpec(pModule1, tkConstraintType1, NULL,
CoreLibBinder::GetModule(), g_pValueTypeClass->GetCl(), NULL, NULL)))))
CoreLibBinder::GetModule(), g_pValueTypeClass->GetCl(), NULL, &newVisited)))))
{
HENUMInternalHolder hEnum2(pInternalImport2);
mdGenericParamConstraint tkConstraint2;
Expand All @@ -4882,7 +4888,7 @@ BOOL MetaSig::CompareVariableConstraints(const Substitution *pSubst1,
IfFailThrow(pInternalImport2->GetGenericParamConstraintProps(tkConstraint2, &tkParam2, &tkConstraintType2));
_ASSERTE(tkParam2 == tok2);

found = CompareTypeDefOrRefOrSpec(pModule1, tkConstraintType1, pSubst1, pModule2, tkConstraintType2, pSubst2, NULL);
found = CompareTypeDefOrRefOrSpec(pModule1, tkConstraintType1, pSubst1, pModule2, tkConstraintType2, pSubst2, &newVisited);
}
if (!found)
{
Expand Down
5 changes: 3 additions & 2 deletions src/coreclr/vm/siginfo.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -432,9 +432,10 @@ class Substitution
// infinite recursion when types refer to each other in a cycle, e.g. a delegate that takes itself as
// a parameter or a struct that declares a field of itself (illegal but we don't know at this point).
//
class TokenPairList
class TokenPairList final
{
public:

// Chain using this constructor when comparing two typedefs for equivalence.
TokenPairList(mdToken token1, ModuleBase *pModule1, mdToken token2, ModuleBase *pModule2, TokenPairList *pNext)
: m_token1(token1), m_token2(token2),
Expand Down Expand Up @@ -470,7 +471,6 @@ class TokenPairList
static TokenPairList AdjustForTypeSpec(TokenPairList *pTemplate, ModuleBase *pTypeSpecModule, PCCOR_SIGNATURE pTypeSpecSig, DWORD cbTypeSpecSig);
static TokenPairList AdjustForTypeEquivalenceForbiddenScope(TokenPairList *pTemplate);

private:
TokenPairList(TokenPairList *pTemplate)
: m_token1(pTemplate ? pTemplate->m_token1 : mdTokenNil),
m_token2(pTemplate ? pTemplate->m_token2 : mdTokenNil),
Expand All @@ -480,6 +480,7 @@ class TokenPairList
m_pNext(pTemplate ? pTemplate->m_pNext : NULL)
{ LIMITED_METHOD_CONTRACT; }

private:
mdToken m_token1, m_token2;
ModuleBase *m_pModule1, *m_pModule2;
BOOL m_bInTypeEquivalenceForbiddenScope;
Expand Down