Skip to content

Commit ea0b132

Browse files
committed
Fail if EnC targets an Async method
1 parent 813c2ec commit ea0b132

File tree

5 files changed

+125
-105
lines changed

5 files changed

+125
-105
lines changed

src/coreclr/vm/class.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,17 @@ HRESULT EEClass::AddMethodDesc(
661661
PCCOR_SIGNATURE sig;
662662
if (FAILED(hr = pImport->GetSigOfMethodDef(methodDef, &sigLen, &sig)))
663663
return hr;
664+
665+
SigParser sigParser(sig, sigLen);
666+
ULONG offsetOfAsyncDetails;
667+
bool isValueTask;
668+
MethodReturnKind returnKind = ClassifyMethodReturnKind(sigParser, pModule, &offsetOfAsyncDetails, &isValueTask);
669+
if (returnKind != MethodReturnKind::NormalMethod)
670+
{
671+
LOG((LF_ENC, LL_INFO100, "**Error** EnC for Async methods is NYI"));
672+
return E_FAIL;
673+
}
674+
664675
uint32_t callConv = CorSigUncompressData(sig);
665676
DWORD classification = (callConv & IMAGE_CEE_CS_CALLCONV_GENERIC)
666677
? mcInstantiated

src/coreclr/vm/encee.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,12 @@ HRESULT EditAndContinueModule::UpdateMethod(MethodDesc *pMethod)
344344
}
345345
CONTRACTL_END;
346346

347+
if (pMethod->HasAsyncMethodData())
348+
{
349+
LOG((LF_ENC, LL_INFO100, "**Error** EnC for Async methods is NYI"));
350+
return E_FAIL;
351+
}
352+
347353
// Notify the debugger of the update
348354
if (CORDebuggerAttached())
349355
{

src/coreclr/vm/method.cpp

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2332,6 +2332,111 @@ MethodDesc* NonVirtualEntry2MethodDesc(PCODE entryPoint)
23322332
}
23332333
}
23342334

2335+
static void GetNameOfTypeDefOrRef(Module* pModule, mdToken tk, LPCSTR* pName, LPCSTR* pNamespace)
2336+
{
2337+
*pName = "";
2338+
*pNamespace = "";
2339+
if (TypeFromToken(tk) == mdtTypeDef)
2340+
{
2341+
IfFailThrow(pModule->GetMDImport()->GetNameOfTypeDef(tk, pName, pNamespace));
2342+
}
2343+
else if (TypeFromToken(tk) == mdtTypeRef)
2344+
{
2345+
IfFailThrow(pModule->GetMDImport()->GetNameOfTypeRef(tk, pNamespace, pName));
2346+
}
2347+
}
2348+
2349+
bool IsTypeDefOrRefImplementedInSystemModule(Module* pModule, mdToken tk)
2350+
{
2351+
if (TypeFromToken(tk) == mdtTypeDef)
2352+
{
2353+
if (pModule->IsSystem())
2354+
{
2355+
return true;
2356+
}
2357+
}
2358+
else if (TypeFromToken(tk) == mdtTypeRef)
2359+
{
2360+
mdToken tkTypeDef;
2361+
Module* pModuleOfTypeDef;
2362+
2363+
ClassLoader::ResolveTokenToTypeDefThrowing(pModule, tk, &pModuleOfTypeDef, &tkTypeDef);
2364+
if (pModuleOfTypeDef->IsSystem())
2365+
{
2366+
return true;
2367+
}
2368+
}
2369+
2370+
return false;
2371+
}
2372+
2373+
MethodReturnKind ClassifyMethodReturnKind(SigPointer sig, Module* pModule, ULONG* offsetOfAsyncDetails, bool *isValueTask)
2374+
{
2375+
// Without FEATURE_RUNTIME_ASYNC every declared method is classified as a NormalMethod.
2376+
// Thus code that handles runtime async scenarios becomes unreachable.
2377+
#ifdef FEATURE_RUNTIME_ASYNC
2378+
PCCOR_SIGNATURE initialSig = sig.GetPtr();
2379+
uint32_t data;
2380+
IfFailThrow(sig.GetCallingConvInfo(&data));
2381+
if (data & IMAGE_CEE_CS_CALLCONV_GENERIC)
2382+
{
2383+
// Skip over generic argument count
2384+
IfFailThrow(sig.GetData(&data));
2385+
}
2386+
2387+
// skip argument count
2388+
IfFailThrow(sig.GetData(&data));
2389+
2390+
// now look at return type
2391+
// NOTE: this will skip modifiers
2392+
CorElementType elemType;
2393+
IfFailThrow(sig.GetElemType(&elemType));
2394+
2395+
// can't reason about ELEMENT_TYPE_INTERNAL, but should not see it in metadata
2396+
if (elemType == ELEMENT_TYPE_INTERNAL)
2397+
ThrowHR(COR_E_BADIMAGEFORMAT);
2398+
2399+
*offsetOfAsyncDetails = (ULONG)(sig.GetPtr() - initialSig) - 1;
2400+
LPCSTR name, _namespace;
2401+
mdToken tk;
2402+
if (elemType == ELEMENT_TYPE_GENERICINST)
2403+
{
2404+
IfFailThrow(sig.GetElemType(&elemType));
2405+
// can't reason about ELEMENT_TYPE_INTERNAL, but should not see it in metadata
2406+
if (elemType == ELEMENT_TYPE_INTERNAL)
2407+
ThrowHR(COR_E_BADIMAGEFORMAT);
2408+
2409+
*isValueTask = (elemType == ELEMENT_TYPE_VALUETYPE);
2410+
IfFailThrow(sig.GetToken(&tk));
2411+
IfFailThrow(sig.GetData(&data));
2412+
if (data == 1)
2413+
{
2414+
// This might be System.Threading.Tasks.Task`1
2415+
GetNameOfTypeDefOrRef(pModule, tk, &name, &_namespace);
2416+
if ((strcmp(name, *isValueTask ? "ValueTask`1" : "Task`1") == 0) && strcmp(_namespace, "System.Threading.Tasks") == 0)
2417+
{
2418+
if (IsTypeDefOrRefImplementedInSystemModule(pModule, tk))
2419+
return MethodReturnKind::GenericTaskReturningMethod;
2420+
}
2421+
}
2422+
}
2423+
else if ((elemType == ELEMENT_TYPE_CLASS) || (elemType == ELEMENT_TYPE_VALUETYPE))
2424+
{
2425+
IfFailThrow(sig.GetToken(&tk));
2426+
*isValueTask = (elemType == ELEMENT_TYPE_VALUETYPE);
2427+
// This might be System.Threading.Tasks.Task or ValueTask
2428+
GetNameOfTypeDefOrRef(pModule, tk, &name, &_namespace);
2429+
if ((strcmp(name, *isValueTask ? "ValueTask" : "Task") == 0) && strcmp(_namespace, "System.Threading.Tasks") == 0)
2430+
{
2431+
if (IsTypeDefOrRefImplementedInSystemModule(pModule, tk))
2432+
return MethodReturnKind::NonGenericTaskReturningMethod;
2433+
}
2434+
}
2435+
#endif // FEATURE_RUNTIME_ASYNC
2436+
2437+
return MethodReturnKind::NormalMethod;
2438+
}
2439+
23352440
//*******************************************************************************
23362441
BOOL MethodDesc::IsPointingToPrestub()
23372442
{

src/coreclr/vm/method.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,9 @@ enum class MethodReturnKind
247247
NonGenericTaskReturningMethod
248248
};
249249

250+
bool IsTypeDefOrRefImplementedInSystemModule(Module* pModule, mdToken tk);
251+
MethodReturnKind ClassifyMethodReturnKind(SigPointer sig, Module* pModule, ULONG* offsetOfAsyncDetails, bool *isValueTask);
252+
250253
inline bool IsTaskReturning(MethodReturnKind input)
251254
{
252255
return (input == MethodReturnKind::GenericTaskReturningMethod) ||

src/coreclr/vm/methodtablebuilder.cpp

Lines changed: 0 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -2691,111 +2691,6 @@ HRESULT MethodTableBuilder::FindMethodDeclarationForMethodImpl(
26912691
#pragma warning(disable:21000) // Suppress PREFast warning about overly large function
26922692
#endif // _PREFAST_
26932693

2694-
static void GetNameOfTypeDefOrRef(Module* pModule, mdToken tk, LPCSTR* pName, LPCSTR* pNamespace)
2695-
{
2696-
*pName = "";
2697-
*pNamespace = "";
2698-
if (TypeFromToken(tk) == mdtTypeDef)
2699-
{
2700-
IfFailThrow(pModule->GetMDImport()->GetNameOfTypeDef(tk, pName, pNamespace));
2701-
}
2702-
else if (TypeFromToken(tk) == mdtTypeRef)
2703-
{
2704-
IfFailThrow(pModule->GetMDImport()->GetNameOfTypeRef(tk, pNamespace, pName));
2705-
}
2706-
}
2707-
2708-
static bool IsTypeDefOrRefImplementedInSystemModule(Module* pModule, mdToken tk)
2709-
{
2710-
if (TypeFromToken(tk) == mdtTypeDef)
2711-
{
2712-
if (pModule->IsSystem())
2713-
{
2714-
return true;
2715-
}
2716-
}
2717-
else if (TypeFromToken(tk) == mdtTypeRef)
2718-
{
2719-
mdToken tkTypeDef;
2720-
Module* pModuleOfTypeDef;
2721-
2722-
ClassLoader::ResolveTokenToTypeDefThrowing(pModule, tk, &pModuleOfTypeDef, &tkTypeDef);
2723-
if (pModuleOfTypeDef->IsSystem())
2724-
{
2725-
return true;
2726-
}
2727-
}
2728-
2729-
return false;
2730-
}
2731-
2732-
static MethodReturnKind ClassifyMethodReturnKind(SigPointer sig, Module* pModule, ULONG* offsetOfAsyncDetails, bool *isValueTask)
2733-
{
2734-
// Without FEATURE_RUNTIME_ASYNC every declared method is classified as a NormalMethod.
2735-
// Thus code that handles runtime async scenarios becomes unreachable.
2736-
#ifdef FEATURE_RUNTIME_ASYNC
2737-
PCCOR_SIGNATURE initialSig = sig.GetPtr();
2738-
uint32_t data;
2739-
IfFailThrow(sig.GetCallingConvInfo(&data));
2740-
if (data & IMAGE_CEE_CS_CALLCONV_GENERIC)
2741-
{
2742-
// Skip over generic argument count
2743-
IfFailThrow(sig.GetData(&data));
2744-
}
2745-
2746-
// skip argument count
2747-
IfFailThrow(sig.GetData(&data));
2748-
2749-
// now look at return type
2750-
// NOTE: this will skip modifiers
2751-
CorElementType elemType;
2752-
IfFailThrow(sig.GetElemType(&elemType));
2753-
2754-
// can't reason about ELEMENT_TYPE_INTERNAL, but should not see it in metadata
2755-
if (elemType == ELEMENT_TYPE_INTERNAL)
2756-
ThrowHR(COR_E_BADIMAGEFORMAT);
2757-
2758-
*offsetOfAsyncDetails = (ULONG)(sig.GetPtr() - initialSig) - 1;
2759-
LPCSTR name, _namespace;
2760-
mdToken tk;
2761-
if (elemType == ELEMENT_TYPE_GENERICINST)
2762-
{
2763-
IfFailThrow(sig.GetElemType(&elemType));
2764-
// can't reason about ELEMENT_TYPE_INTERNAL, but should not see it in metadata
2765-
if (elemType == ELEMENT_TYPE_INTERNAL)
2766-
ThrowHR(COR_E_BADIMAGEFORMAT);
2767-
2768-
*isValueTask = (elemType == ELEMENT_TYPE_VALUETYPE);
2769-
IfFailThrow(sig.GetToken(&tk));
2770-
IfFailThrow(sig.GetData(&data));
2771-
if (data == 1)
2772-
{
2773-
// This might be System.Threading.Tasks.Task`1
2774-
GetNameOfTypeDefOrRef(pModule, tk, &name, &_namespace);
2775-
if ((strcmp(name, *isValueTask ? "ValueTask`1" : "Task`1") == 0) && strcmp(_namespace, "System.Threading.Tasks") == 0)
2776-
{
2777-
if (IsTypeDefOrRefImplementedInSystemModule(pModule, tk))
2778-
return MethodReturnKind::GenericTaskReturningMethod;
2779-
}
2780-
}
2781-
}
2782-
else if ((elemType == ELEMENT_TYPE_CLASS) || (elemType == ELEMENT_TYPE_VALUETYPE))
2783-
{
2784-
IfFailThrow(sig.GetToken(&tk));
2785-
*isValueTask = (elemType == ELEMENT_TYPE_VALUETYPE);
2786-
// This might be System.Threading.Tasks.Task or ValueTask
2787-
GetNameOfTypeDefOrRef(pModule, tk, &name, &_namespace);
2788-
if ((strcmp(name, *isValueTask ? "ValueTask" : "Task") == 0) && strcmp(_namespace, "System.Threading.Tasks") == 0)
2789-
{
2790-
if (IsTypeDefOrRefImplementedInSystemModule(pModule, tk))
2791-
return MethodReturnKind::NonGenericTaskReturningMethod;
2792-
}
2793-
}
2794-
#endif // FEATURE_RUNTIME_ASYNC
2795-
2796-
return MethodReturnKind::NormalMethod;
2797-
}
2798-
27992694
//---------------------------------------------------------------------------------------
28002695
//
28012696
// Used by BuildMethodTable

0 commit comments

Comments
 (0)