Skip to content

Commit

Permalink
Fix value type with static method fails to load (#76262)
Browse files Browse the repository at this point in the history
* Allow static methods if checking type equivalence

* Add test for loading value type with static method

* Add test in which loading a value type with an instance method should throw a TypeLoadException
  • Loading branch information
JJamesWWang authored Sep 29, 2022
1 parent e5d2c3e commit 48468d1
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 8 deletions.
16 changes: 8 additions & 8 deletions src/coreclr/vm/methodtablebuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2659,14 +2659,6 @@ MethodTableBuilder::EnumerateClassMethods()
METHOD_IMPL_TYPE implType;
LPSTR strMethodName;

#ifdef FEATURE_TYPEEQUIVALENCE
// TypeEquivalent structs must not have methods
if (bmtProp->fIsTypeEquivalent && fIsClassValueType)
{
BuildMethodTableThrowException(IDS_CLASSLOAD_EQUIVALENTSTRUCTMETHODS);
}
#endif

//
// Go to the next method and retrieve its attributes.
//
Expand All @@ -2686,6 +2678,14 @@ MethodTableBuilder::EnumerateClassMethods()
BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
}

#ifdef FEATURE_TYPEEQUIVALENCE
// TypeEquivalent structs must not have non-static methods
if (!IsMdStatic(dwMemberAttrs) && bmtProp->fIsTypeEquivalent && fIsClassValueType)
{
BuildMethodTableThrowException(IDS_CLASSLOAD_EQUIVALENTSTRUCTMETHODS);
}
#endif

bool isVtblGap = false;
if (IsMdRTSpecialName(dwMemberAttrs) || IsMdVirtual(dwMemberAttrs) || IsDelegate())
{
Expand Down
9 changes: 9 additions & 0 deletions src/tests/baseservices/typeequivalence/pia/PIAContract.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Library</OutputType>
<CLRTestKind>SharedLibrary</CLRTestKind>
</PropertyGroup>
<ItemGroup>
<Compile Include="Types.cs" />
</ItemGroup>
</Project>
19 changes: 19 additions & 0 deletions src/tests/baseservices/typeequivalence/pia/Types.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Runtime.InteropServices;

[assembly: PrimaryInteropAssembly(1, 0)]

public struct ValueTypeWithStaticMethod
{
public int F;
public static void M() { }
}

public struct ValueTypeWithInstanceMethod
{
public int F;
public void M() { }
}
16 changes: 16 additions & 0 deletions src/tests/baseservices/typeequivalence/simple/Simple.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Linq;
using System.Text;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

using Xunit;
Expand Down Expand Up @@ -253,6 +254,20 @@ private static unsafe void TestTypeEquivalenceWithTypePunning()
}
}

[MethodImpl (MethodImplOptions.NoInlining)]
private static void TestLoadingValueTypesWithMethod()
{
Console.WriteLine($"{nameof(TestLoadingValueTypesWithMethod)}");
Console.WriteLine($"-- {typeof(ValueTypeWithStaticMethod).Name}");
Assert.Throws<TypeLoadException>(() => LoadInvalidType());
}

[MethodImpl (MethodImplOptions.NoInlining)]
private static void LoadInvalidType()
{
Console.WriteLine($"-- {typeof(ValueTypeWithInstanceMethod).Name}");
}

public static int Main(string[] noArgs)
{
if (!OperatingSystem.IsWindows())
Expand All @@ -270,6 +285,7 @@ public static int Main(string[] noArgs)
TestGenericClassNonEquivalence();
TestGenericInterfaceEquivalence();
TestTypeEquivalenceWithTypePunning();
TestLoadingValueTypesWithMethod();
}
catch (Exception e)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<ProjectReference Include="../impl/TypeImpl.csproj" />
<ProjectReference Include="../impl/PunningLib.ilproj" />
<ProjectReference Include="$(TestSourceDir)Common/CoreCLRTestLibrary/CoreCLRTestLibrary.csproj" />
<ProjectReference Include="../pia/PIAContract.csproj" />
</ItemGroup>
<Import Project="$([MSBuild]::GetPathOfFileAbove(TypeEquivalence.targets))" />
</Project>

0 comments on commit 48468d1

Please sign in to comment.