dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
14.93k stars 4.64k forks source link

[mono][ppc64le] aspnetcore tests are failing with error "System.InvalidCastException : Specified cast is not valid." on ppc64le #94898

Open vikasgupta8 opened 9 months ago

vikasgupta8 commented 9 months ago

Description

Aspnetcore tests are failing on ppc6le while testing cross build .net 8.0.100-rc.2.23502.2 mono build.

Stack trace:

Microsoft.AspNetCore.Server.Kestrel.Core.Tests.ConnectionContextTests.ParameterlessAbortCreateConnectionAbortedException
System.InvalidCastException : Specified cast is not valid.
  at Castle.DynamicProxy.Internal.AttributeUtil.ReadAttributeValue(CustomAttributeTypedArgument argument)
  at Castle.DynamicProxy.Internal.AttributeUtil.GetArguments(IList`1 constructorArguments, Type[]& constructorArgTypes, Object[]& constructorArgs)
  at Castle.DynamicProxy.Internal.AttributeUtil.CreateInfo(CustomAttributeData attribute)
  at Castle.DynamicProxy.Internal.AttributeUtil.GetNonInheritableAttributes(MemberInfo member)+MoveNext()
  at System.Linq.Enumerable.SelectEnumerableIterator`2[[Castle.DynamicProxy.CustomAttributeInfo, Castle.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc],[System.Reflection.Emit.CustomAttributeBuilder, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext()
  at Castle.DynamicProxy.Generators.MetaProperty.BuildPropertyEmitter(ClassEmitter classEmitter)
  at Castle.DynamicProxy.Contributors.CompositeTypeContributor.ImplementProperty(ClassEmitter emitter, MetaProperty property, ProxyGenerationOptions options)
  at Castle.DynamicProxy.Contributors.CompositeTypeContributor.Generate(ClassEmitter class, ProxyGenerationOptions options)
  at Castle.DynamicProxy.Generators.ClassProxyGenerator.GenerateType(String name, Type[] interfaces, INamingScope namingScope)
  at Castle.DynamicProxy.Generators.ClassProxyGenerator.<>c__DisplayClass1_0.<GenerateCode>b__0(String n, INamingScope s)
  at Castle.DynamicProxy.Generators.BaseProxyGenerator.ObtainProxyType(CacheKey cacheKey, Func`3 factory)
  at Castle.DynamicProxy.Generators.ClassProxyGenerator.GenerateCode(Type[] interfaces, ProxyGenerationOptions options)
  at Castle.DynamicProxy.DefaultProxyBuilder.CreateClassProxyType(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options)
  at Castle.DynamicProxy.ProxyGenerator.CreateClassProxyType(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options)
  at Castle.DynamicProxy.ProxyGenerator.CreateClassProxy(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options, Object[] constructorArguments, IInterceptor[] interceptors)
  at Moq.CastleProxyFactory.CreateProxy(Type mockType, IInterceptor interceptor, Type[] interfaces, Object[] arguments)
  at Moq.Mock`1[[Microsoft.AspNetCore.Connections.ConnectionContext, Microsoft.AspNetCore.Connections.Abstractions, Version=8.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60]].InitializeInstancePexProtected()
  at Moq.PexProtector.Invoke(Action action)
  at Moq.Mock`1[[Microsoft.AspNetCore.Connections.ConnectionContext, Microsoft.AspNetCore.Connections.Abstractions, Version=8.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60]].InitializeInstance()
  at Moq.Mock`1[[Microsoft.AspNetCore.Connections.ConnectionContext, Microsoft.AspNetCore.Connections.Abstractions, Version=8.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60]].OnGetObject()
  at Moq.Mock.get_Object()
  at Moq.Mock`1[[Microsoft.AspNetCore.Connections.ConnectionContext, Microsoft.AspNetCore.Connections.Abstractions, Version=8.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60]].get_Object()
  at Microsoft.AspNetCore.Server.Kestrel.Core.Tests.ConnectionContextTests.ParameterlessAbortCreateConnectionAbortedException() in /_/src/Servers/Kestrel/Core/test/ConnectionContextTests.cs:line 21
  at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
  at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)

Reproduction Steps

I have written sample program that reproduce the issue on ppc64le with mono .net8 rc2 When casting Value to CustomAttributeTypedArgument.

Use the dotnet 8.0.100-rc.2.23502.2 cross build sdk.

.NET SDK:
 Version:   8.0.100-rc.2.23502.2
 Commit:    0abacfc2b6

Runtime Environment:
 OS Name:     ubuntu
 OS Version:  20.04
 OS Platform: Linux
 RID:         linux-ppc64le
 Base Path:   /home/ubuntu/vikas/dotnet-ppc64le-8.0.100-rc.2.23502.2/.dotnet/sdk/8.0.100-rc.2.23502.2/

.NET workloads installed:
There are no installed workloads to display.

Host:
  Version:      8.0.0-rc.2.23479.6
  Architecture: ppc64le
  Commit:       0b25e38ad3

.NET SDKs installed:
  8.0.100-rc.2.23502.2 [/home/ubuntu/vikas/dotnet-ppc64le-8.0.100-rc.2.23502.2/.dotnet/sdk]

Program.cs

using System.Reflection;

namespace Test
{
        public class Testing
        {
            public sealed class AttributeWithIntArrayArgument : Attribute
            {
                public AttributeWithIntArrayArgument(params int[] ints)
                {
                }
            }

            [AttributeWithIntArrayArgument(1, 2, 3)]
            public interface IHasAttributeWithIntArray
            {
            }

            public void TestTypeCast_Fail()
            {
                Type targetType = typeof(IHasAttributeWithIntArray);

                var attributes = targetType.CustomAttributes;
                foreach (var attribute in attributes)
                {
                    Console.WriteLine("VIKAS -> attribute.ConstructorArguments[0].ArgumentType = {0}",attribute.ConstructorArguments[0].ArgumentType);
                    Console.WriteLine("VIKAS -> attribute.ConstructorArguments[0].Value = {0}",attribute.ConstructorArguments[0].Value);
                    var cast = (IList<CustomAttributeTypedArgument>)attribute.ConstructorArguments[0].Value;
                }
            }

            static void Main(string[] args)
            {
                Testing p1 = new Testing();
                p1.TestTypeCast_Fail();
            }
        }
}

This throws InvalidCastException on ppc6le(Mono) while works fine on intel x86(CoreClr).

Output on ppc64le (Mono)

VIKAS -> attribute.ConstructorArguments[0].ArgumentType = System.Int32[]
VIKAS -> attribute.ConstructorArguments[0].Value = System.Int32[]

Unhandled Exception:
System.InvalidCastException: Specified cast is not valid.
   at vikas.Testing.TestTypeCast_Fail() in /root/vikas/Castle.Core.Tests/Sample/Program.cs:line 28
   at vikas.Testing.Main(String[] args) in /root/vikas/Castle.Core.Tests/Sample/Program.cs:line 35

Output on x86 intel (CoreClr)

VIKAS -> attribute.ConstructorArguments[0].ArgumentType = System.Int32[]
VIKAS -> attribute.ConstructorArguments[0].Value = System.Collections.ObjectModel.ReadOnlyCollection`1[System.Reflection.CustomAttributeTypedArgument]

Expected behavior

Aspnetcore tests should pass without any exception.

Actual behavior

Tests are failing with InvalidCastException

System.InvalidCastException: Specified cast is not valid.

Regression?

No response

Known Workarounds

If we update CastleCore version from 4.2.1 to 5.1.1 In aspnetcore/eng/Versions.props file then test failures observed in Microsoft.AspNetCore.Server.Kestrel.Core.Tests gets fixed.

Configuration

No response

Other information

CC: @uweigand @janani66 @Sapana-Khemkar

vikasgupta8 commented 9 months ago

Tagging @lambdageek

vcsjones commented 9 months ago

This looks like a duplicate of https://github.com/dotnet/runtime/issues/93770.

uweigand commented 9 months ago

This looks like a duplicate of #93770.

Unfortunately not - running the aspnetcore tests uncovered a variety of different problems, one of those was addressed in #93770, two others were already spun off into separate issues (https://github.com/dotnet/runtime/issues/94488 and https://github.com/dotnet/runtime/issues/94490), and this issue is covering the last remaining problem in that area.

lambdageek commented 9 months ago

Also repros on linux-x64 with -p:UseMonoRuntime=true -p:SelfContained=true

lambdageek commented 9 months ago

Looks like ves_icall_System_Reflection_RuntimeCustomAttributeData_ResolveArgumentsInternal doesn't do the correct encoding of custom attribute data for array types (or indeed any types, but particularly arrays) - it just encodes the value as an array object of the element values.

By contrast the corresponding core (I think... it's hard to follow) in CoreCLR recursively creates another struct (that will eventually become an array of CustomAttributeTypedArgument)

https://github.com/dotnet/runtime/blob/83f116627e2548c7a55b3701bd5448570b84a784/src/coreclr/vm/customattribute.cpp#L287-L301

lambdageek commented 9 months ago

/cc @SamMonoRT