Version Used:
Microsoft Visual Studio Enterprise 2017 Preview
Version 15.5.0 Preview 1.0
Steps to Reproduce:
Expected Behavior:
The program prints "Comparison: 0"
Actual Behavior:
The program crashes with a VerificationException in StructyMcStructFace.CompareTo.
Code:
using System;
using System.Security;
[assembly: AllowPartiallyTrustedCallers()]
namespace RoslynRepro155
{
class Program
{
static void Main(string[] args)
{
var color1 = new StructyMcStructFace(TColorType.Automatic);
var color2 = new StructyMcStructFace(TColorType.Automatic);
var result = color1.CompareTo(color2);
Console.WriteLine("Comparison: {0}", result);
Console.ReadKey();
}
}
public enum TAutomaticColor
{
}
public enum TColorType
{
Automatic,
RGB,
Theme,
Indexed
}
public struct StructyMcStructFace
{
public StructyMcStructFace(TColorType type)
{
ColorType = type;
automaticType = default(TAutomaticColor);
}
readonly TAutomaticColor automaticType;
public TColorType ColorType { get; }
public int CompareTo(StructyMcStructFace other)
{
switch (ColorType)
{
case TColorType.Automatic:
return automaticType.CompareTo(other.automaticType);
}
return 0;
}
}
}
IL of CompareTo with Visual Studio 2017 v15.4.0:
.method public hidebysig
instance int32 CompareTo (
valuetype RoslynRepro155.StructyMcStructFace other
) cil managed
{
// Method begins at RVA 0x20b0
// Code size 53 (0x35)
.maxstack 2
.locals init (
[0] valuetype RoslynRepro155.TColorType,
[1] valuetype RoslynRepro155.TAutomaticColor,
[2] int32
)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: call instance valuetype RoslynRepro155.TColorType RoslynRepro155.StructyMcStructFace::get_ColorType()
IL_0007: stloc.0
IL_0008: ldloc.0
IL_0009: brfalse.s IL_000d
IL_000b: br.s IL_002f
IL_000d: ldarg.0
IL_000e: ldfld valuetype RoslynRepro155.TAutomaticColor RoslynRepro155.StructyMcStructFace::automaticType
IL_0013: stloc.1
IL_0014: ldloca.s 1
IL_0016: ldarg.1
IL_0017: ldfld valuetype RoslynRepro155.TAutomaticColor RoslynRepro155.StructyMcStructFace::automaticType
IL_001c: box RoslynRepro155.TAutomaticColor
IL_0021: constrained. RoslynRepro155.TAutomaticColor
IL_0027: callvirt instance int32 [mscorlib]System.Enum::CompareTo(object)
IL_002c: stloc.2
IL_002d: br.s IL_0033
IL_002f: ldc.i4.0
IL_0030: stloc.2
IL_0031: br.s IL_0033
IL_0033: ldloc.2
IL_0034: ret
} // end of method StructyMcStructFace::CompareTo
IL of CompareTo with Visual Studio 2017 v15.5.0 Preview:
.method public hidebysig
instance int32 CompareTo (
valuetype RoslynRepro155.StructyMcStructFace other
) cil managed
{
// Method begins at RVA 0x20b0
// Code size 50 (0x32)
.maxstack 2
.locals init (
[0] valuetype RoslynRepro155.TColorType,
[1] int32
)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: call instance valuetype RoslynRepro155.TColorType RoslynRepro155.StructyMcStructFace::get_ColorType()
IL_0007: stloc.0
IL_0008: ldloc.0
IL_0009: brfalse.s IL_000d
IL_000b: br.s IL_002c
IL_000d: ldarg.0
IL_000e: ldflda valuetype RoslynRepro155.TAutomaticColor RoslynRepro155.StructyMcStructFace::automaticType
IL_0013: ldarg.1
IL_0014: ldfld valuetype RoslynRepro155.TAutomaticColor RoslynRepro155.StructyMcStructFace::automaticType
IL_0019: box RoslynRepro155.TAutomaticColor
IL_001e: constrained. RoslynRepro155.TAutomaticColor
IL_0024: callvirt instance int32 [mscorlib]System.Enum::CompareTo(object)
IL_0029: stloc.1
IL_002a: br.s IL_0030
IL_002c: ldc.i4.0
IL_002d: stloc.1
IL_002e: br.s IL_0030
IL_0030: ldloc.1
IL_0031: ret
} // end of method StructyMcStructFace::CompareTo
Tagging @gafter @TyOverby
This seems to be similar to https://github.com/dotnet/roslyn/issues/22485, except here it's not just PEVerify complaining, it's also the runtime, due to the presence of AllowPartiallyTrustedCallers. And the workaround mentioned there does work: adding <Features>peverify-compat</Features> to csproj makes the code work for me in VS 15.5 Preview 1.
Tagging @VSadov. We should probably update the breaking changes doc and give a one-liner there (relates to https://github.com/dotnet/roslyn/pull/21269).
We could also check for things like AllowPartiallyTrustedCallers or security transparent and disable the optimizations that go beyond verification rules on desktop.
logged https://github.com/dotnet/roslyn/issues/22712
At least for APTCA, it seems possible and reasonable to sniff for the attribute and enable compat mode automatically. Same might be true for SecurityTransparent
@VSadov Good to close?
Yes. we have short term a solution that we believe is the right balance between desire to use new features and produce code compatible with old verification rules: https://github.com/dotnet/roslyn/pull/22772
We are also working on extending verification rules:
https://github.com/dotnet/designs/pull/17
https://github.com/dotnet/designs/pull/21
Most helpful comment
This seems to be similar to https://github.com/dotnet/roslyn/issues/22485, except here it's not just PEVerify complaining, it's also the runtime, due to the presence of
AllowPartiallyTrustedCallers. And the workaround mentioned there does work: adding<Features>peverify-compat</Features>to csproj makes the code work for me in VS 15.5 Preview 1.