Skip to content

Commit 8725065

Browse files
authored
Fix handling ldtoken with method generic param (#3181)
1 parent 8a1f072 commit 8725065

File tree

2 files changed

+65
-13
lines changed

2 files changed

+65
-13
lines changed

src/CLR/Core/Execution.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1980,7 +1980,7 @@ HRESULT CLR_RT_ExecutionEngine::InitializeLocals(
19801980
CLR_RT_SignatureParser::Element element;
19811981

19821982
// ensure we don’t walk past the available generic parameters
1983-
const int maxParams = parser.GenParamCount;
1983+
const int maxParams = methodDefInstance.target->genericParamCount;
19841984
if (genericParamPosition < 0 || genericParamPosition > maxParams)
19851985
{
19861986
NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE);

src/CLR/Core/Interpreter.cpp

Lines changed: 64 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3242,22 +3242,74 @@ HRESULT CLR_RT_Thread::Execute_IL(CLR_RT_StackFrame &stackArg)
32423242

32433243
if (stack->m_call.genericType != nullptr)
32443244
{
3245-
// For a method in a generic type, caller->genericType points to the TypeSpec of the
3246-
// closed type
3247-
CLR_UINT32 closedTypeSpecRow = stack->m_call.genericType->TypeSpec();
3245+
CLR_UINT32 rawGenericParamRow = CLR_DataFromTk(arg);
32483246

3249-
CLR_RT_TypeDef_Index resolvedTypeDef;
3250-
NanoCLRDataType resolvedDataType;
3247+
CLR_RT_GenericParam_CrossReference gpCR =
3248+
stack->m_call.assembly->crossReferenceGenericParam[rawGenericParamRow];
32513249

3252-
CLR_UINT32 index = CLR_DataFromTk(arg);
3250+
if (gpCR.typeOrMethodDef == TBL_MethodDef)
3251+
{
3252+
// Method generic parameter (!!T)
32533253

3254-
assm->FindGenericParamAtTypeSpec(
3255-
closedTypeSpecRow,
3256-
index,
3257-
resolvedTypeDef,
3258-
resolvedDataType);
3254+
CLR_RT_MethodSpec_Index msIndex;
3255+
if (!assm->FindMethodSpecFromTypeSpec(
3256+
stack->m_call.genericType->TypeSpec(),
3257+
msIndex))
3258+
{
3259+
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
3260+
}
32593261

3260-
evalPos[0].SetReflection(resolvedTypeDef);
3262+
CLR_RT_MethodSpec_Instance ms;
3263+
if (ms.InitializeFromIndex(msIndex) == false)
3264+
{
3265+
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
3266+
}
3267+
3268+
int genericParamPos = param.GenericParam();
3269+
3270+
CLR_RT_SignatureParser parser;
3271+
CLR_RT_SignatureParser::Element element;
3272+
parser.Initialize_MethodSignature(&ms);
3273+
3274+
for (int i = 0; i <= genericParamPos; i++)
3275+
{
3276+
NANOCLR_CHECK_HRESULT(parser.Advance(element));
3277+
}
3278+
3279+
evalPos[0].SetReflection(element.Class);
3280+
}
3281+
else
3282+
{
3283+
// type generic parameter (!T)
3284+
if (stack->m_call.genericType == nullptr)
3285+
{
3286+
// No closed‐generic context available: fall back to returning the
3287+
// declaring TYPE itself as the reflection result (rarely correct, but at least
3288+
// safe).
3289+
CLR_RT_TypeDef_Index fallbackTypeDef = gpCR.classTypeDef;
3290+
NANOCLR_CHECK_HRESULT(evalPos[0].SetReflection(fallbackTypeDef));
3291+
}
3292+
else
3293+
{
3294+
// closed TypeSpec
3295+
const CLR_RT_TypeSpec_Index *callerTypeSpec = stack->m_call.genericType;
3296+
CLR_RT_TypeDef_Index resolvedTypeDef;
3297+
NanoCLRDataType resolvedDataType;
3298+
3299+
HRESULT hr2 = stack->m_call.assembly->FindGenericParamAtTypeSpec(
3300+
callerTypeSpec->TypeSpec(),
3301+
(CLR_UINT32)gpCR.m_target.GenericParam(),
3302+
resolvedTypeDef,
3303+
resolvedDataType);
3304+
3305+
if (FAILED(hr2))
3306+
{
3307+
NANOCLR_SET_AND_LEAVE(hr2);
3308+
}
3309+
3310+
evalPos[0].SetReflection(resolvedTypeDef);
3311+
}
3312+
}
32613313
}
32623314
else
32633315
{

0 commit comments

Comments
 (0)