Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MetadataExtensions.GetCustomAttributeFullName crashes on generic AssemblyAttribute #9369

Closed
inf9144 opened this issue Oct 3, 2024 · 3 comments · Fixed by #9373
Closed

MetadataExtensions.GetCustomAttributeFullName crashes on generic AssemblyAttribute #9369

inf9144 opened this issue Oct 3, 2024 · 3 comments · Fixed by #9373
Assignees
Labels
Area: App+Library Build Issues when building Library projects or Application projects. need-attention A xamarin-android contributor needs to review

Comments

@inf9144
Copy link

inf9144 commented Oct 3, 2024

Android framework version

net8.0-android

Affected platform version

VS 2022 17.11.4

Description

If you reference assemblies in your project build that are attributed by generic attributes like:

[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true, Inherited = false)]
public class GenericTestAttribute<T> : Attribute { }

[assembly: GenericTestAttribute<SomeType>]

the build crashes with:

C:\Program Files\dotnet\packs\Microsoft.Android.Sdk.Windows\34.0.113\tools\Xamarin.Android.Common.targets(434,3): error XAFLT7007: System.InvalidCastException: Die angegebene Umwandlung ist ungültig.
C:\Program Files\dotnet\packs\Microsoft.Android.Sdk.Windows\34.0.113\tools\Xamarin.Android.Common.targets(434,3): error XAFLT7007:    bei System.Reflection.Throw.InvalidCast()
C:\Program Files\dotnet\packs\Microsoft.Android.Sdk.Windows\34.0.113\tools\Xamarin.Android.Common.targets(434,3): error XAFLT7007:    bei System.Reflection.Metadata.TypeReferenceHandle.op_Explicit(EntityHandle handle)
C:\Program Files\dotnet\packs\Microsoft.Android.Sdk.Windows\34.0.113\tools\Xamarin.Android.Common.targets(434,3): error XAFLT7007:    bei Xamarin.Android.Tasks.MetadataExtensions.GetCustomAttributeFullName(MetadataReader reader, CustomAttribute attribute)
C:\Program Files\dotnet\packs\Microsoft.Android.Sdk.Windows\34.0.113\tools\Xamarin.Android.Common.targets(434,3): error XAFLT7007:    bei Xamarin.Android.Tasks.FilterAssemblies.IsAndroidAssembly(AssemblyDefinition assembly, MetadataReader reader)
C:\Program Files\dotnet\packs\Microsoft.Android.Sdk.Windows\34.0.113\tools\Xamarin.Android.Common.targets(434,3): error XAFLT7007:    bei Xamarin.Android.Tasks.FilterAssemblies.ProcessAssembly(ITaskItem assemblyItem, List`1 output)
C:\Program Files\dotnet\packs\Microsoft.Android.Sdk.Windows\34.0.113\tools\Xamarin.Android.Common.targets(434,3): error XAFLT7007:    bei Xamarin.Android.Tasks.FilterAssemblies.RunTask()
C:\Program Files\dotnet\packs\Microsoft.Android.Sdk.Windows\34.0.113\tools\Xamarin.Android.Common.targets(434,3): error XAFLT7007:    bei Microsoft.Android.Build.Tasks.AndroidTask.Execute() in /Users/runner/work/1/s/xamarin-android/external/xamarin-android-tools/src/Microsoft.Android.Build.BaseTasks/AndroidTask.cs:Line 25.

Steps to Reproduce

  1. Create an Android or MAUI Application
  2. Create a class library project
  3. Reference it
  4. Add an generic attribute to the referenced project.
  5. Build

Did you find any workaround?

Yes - i am the author of the generic attribute and for now fixed it to:

[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true, Inherited = false)]
public class GenericTestAttribute(Type typeFor) : Attribute {
   public Type TypeFor { get; set; } = typeFor;
}

Relevant log output

C:\Program Files\dotnet\packs\Microsoft.Android.Sdk.Windows\34.0.113\tools\Xamarin.Android.Common.targets(434,3): error XAFLT7007: System.InvalidCastException: Die angegebene Umwandlung ist ungültig.
C:\Program Files\dotnet\packs\Microsoft.Android.Sdk.Windows\34.0.113\tools\Xamarin.Android.Common.targets(434,3): error XAFLT7007:    bei System.Reflection.Throw.InvalidCast()
C:\Program Files\dotnet\packs\Microsoft.Android.Sdk.Windows\34.0.113\tools\Xamarin.Android.Common.targets(434,3): error XAFLT7007:    bei System.Reflection.Metadata.TypeReferenceHandle.op_Explicit(EntityHandle handle)
C:\Program Files\dotnet\packs\Microsoft.Android.Sdk.Windows\34.0.113\tools\Xamarin.Android.Common.targets(434,3): error XAFLT7007:    bei Xamarin.Android.Tasks.MetadataExtensions.GetCustomAttributeFullName(MetadataReader reader, CustomAttribute attribute)
C:\Program Files\dotnet\packs\Microsoft.Android.Sdk.Windows\34.0.113\tools\Xamarin.Android.Common.targets(434,3): error XAFLT7007:    bei Xamarin.Android.Tasks.FilterAssemblies.IsAndroidAssembly(AssemblyDefinition assembly, MetadataReader reader)
C:\Program Files\dotnet\packs\Microsoft.Android.Sdk.Windows\34.0.113\tools\Xamarin.Android.Common.targets(434,3): error XAFLT7007:    bei Xamarin.Android.Tasks.FilterAssemblies.ProcessAssembly(ITaskItem assemblyItem, List`1 output)
C:\Program Files\dotnet\packs\Microsoft.Android.Sdk.Windows\34.0.113\tools\Xamarin.Android.Common.targets(434,3): error XAFLT7007:    bei Xamarin.Android.Tasks.FilterAssemblies.RunTask()
C:\Program Files\dotnet\packs\Microsoft.Android.Sdk.Windows\34.0.113\tools\Xamarin.Android.Common.targets(434,3): error XAFLT7007:    bei Microsoft.Android.Build.Tasks.AndroidTask.Execute() in /Users/runner/work/1/s/xamarin-android/external/xamarin-android-tools/src/Microsoft.Android.Build.BaseTasks/AndroidTask.cs:Line 25.
@inf9144 inf9144 added Area: App+Library Build Issues when building Library projects or Application projects. needs-triage Issues that need to be assigned. labels Oct 3, 2024
@dellis1972 dellis1972 removed the needs-triage Issues that need to be assigned. label Oct 4, 2024
@jonathanpeppers
Copy link
Member

@inf9144 I tried it in one of our MSBuild integration tests, but this passes:

main...jonathanpeppers:xamarin-android:dev/peppers/genericattribute

Do I need to set up something differently? Do you have a sample you can share?

@jonathanpeppers jonathanpeppers self-assigned this Oct 4, 2024
@jonathanpeppers jonathanpeppers added the need-info Issues that need more information from the author. label Oct 4, 2024
dellis1972 added a commit that referenced this issue Oct 4, 2024
Fixes #9369

When System.Reflection.Metadata comes across an Attribute
which has a generic, it does NOT return a `TypeReferenceHandle`.
It returns a `TypeSpecificationHandle`.

Tying to cast the type results in the following error

```
System.InvalidCastException: Die angegebene Umwandlung ist ungültig.
error XAFLT7007:    bei System.Reflection.Throw.InvalidCast()
error XAFLT7007:    bei System.Reflection.Metadata.TypeReferenceHandle.op_Explicit(EntityHandle handle)
error XAFLT7007:    bei Xamarin.Android.Tasks.MetadataExtensions.GetCustomAttributeFullName(MetadataReader reader, CustomAttribute attribute)
error XAFLT7007:    bei Xamarin.Android.Tasks.FilterAssemblies.IsAndroidAssembly(AssemblyDefinition assembly, MetadataReader reader)
error XAFLT7007:    bei Xamarin.Android.Tasks.FilterAssemblies.ProcessAssembly(ITaskItem assemblyItem, List`1 output)
error XAFLT7007:    bei Xamarin.Android.Tasks.FilterAssemblies.RunTask()
error XAFLT7007:    bei Microsoft.Android.Build.Tasks.AndroidTask.Execute()
```

So we need to handle this case, and put in place a backup to handle
an `InvalidCastException` so that we never hit this issue again.
@inf9144
Copy link
Author

inf9144 commented Oct 7, 2024

@inf9144 I tried it in one of our MSBuild integration tests, but this passes:

main...jonathanpeppers:xamarin-android:dev/peppers/genericattribute

Do I need to set up something differently? Do you have a sample you can share?

I reproduced it a second time - crashes on VS 17.11.4 with standard MauiApp template and two class Libraries

ClassLibrary2 content:

namespace ClassLibrary2;

[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
public class AssemblyTestAttribute<T> : Attribute;

public class Class2 {

}

ClassLibrary1 references ClassLibrary2:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <ProjectReference Include="..\ClassLibrary2\ClassLibrary2.csproj" />
  </ItemGroup>

</Project>

ClassLibrary1 content:

using ClassLibrary1;
using ClassLibrary2;

[assembly: AssemblyTest<Class1>]
[assembly: AssemblyTest<Class2>]

namespace ClassLibrary1;

public class Class1 {

}

MauiApp references ClassLibrary1:

<Project Sdk="Microsoft.NET.Sdk">
   ... MauiApp Template Content ...

	<ItemGroup>
	  <ProjectReference Include="..\ClassLibrary1\ClassLibrary1.csproj" />
	</ItemGroup>

</Project>

I hope that helps :-)

@dotnet-policy-service dotnet-policy-service bot added need-attention A xamarin-android contributor needs to review and removed need-info Issues that need more information from the author. labels Oct 7, 2024
@dellis1972
Copy link
Contributor

@inf9144 thanks, we already have a PR up with a fix #9373

dellis1972 added a commit that referenced this issue Oct 7, 2024
Fixes #9369

When System.Reflection.Metadata comes across an Attribute
which has a generic, it does NOT return a `TypeReferenceHandle`.
It returns a `TypeSpecificationHandle`.

Tying to cast the type results in the following error

```
System.InvalidCastException: Die angegebene Umwandlung ist ungültig.
error XAFLT7007:    bei System.Reflection.Throw.InvalidCast()
error XAFLT7007:    bei System.Reflection.Metadata.TypeReferenceHandle.op_Explicit(EntityHandle handle)
error XAFLT7007:    bei Xamarin.Android.Tasks.MetadataExtensions.GetCustomAttributeFullName(MetadataReader reader, CustomAttribute attribute)
error XAFLT7007:    bei Xamarin.Android.Tasks.FilterAssemblies.IsAndroidAssembly(AssemblyDefinition assembly, MetadataReader reader)
error XAFLT7007:    bei Xamarin.Android.Tasks.FilterAssemblies.ProcessAssembly(ITaskItem assemblyItem, List`1 output)
error XAFLT7007:    bei Xamarin.Android.Tasks.FilterAssemblies.RunTask()
error XAFLT7007:    bei Microsoft.Android.Build.Tasks.AndroidTask.Execute()
```

So we need to handle this case, and put in place a backup to handle
an `InvalidCastException` so that we never hit this issue again.
jonpryor pushed a commit that referenced this issue Oct 8, 2024
…9373)

Fixes: #9369

[C# 11 added support for generic custom attributes][0]:

	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true, Inherited = false)]
	public class GenericTestAttribute<T> : Attribute {
	}

which means generic types can now be used as assembly-level attributes:

	[assembly: GenericTestAttribute<string>]

Unfortunately, attempting to do this would result in an
`InvalidCastException` from the `<FilterAssemblies/>` task:

	System.InvalidCastException: Die angegebene Umwandlung ist ungültig.
	error XAFLT7007:    bei System.Reflection.Throw.InvalidCast()
	error XAFLT7007:    bei System.Reflection.Metadata.TypeReferenceHandle.op_Explicit(EntityHandle handle)
	error XAFLT7007:    bei Xamarin.Android.Tasks.MetadataExtensions.GetCustomAttributeFullName(MetadataReader reader, CustomAttribute attribute)
	error XAFLT7007:    bei Xamarin.Android.Tasks.FilterAssemblies.IsAndroidAssembly(AssemblyDefinition assembly, MetadataReader reader)
	error XAFLT7007:    bei Xamarin.Android.Tasks.FilterAssemblies.ProcessAssembly(ITaskItem assemblyItem, List`1 output)
	error XAFLT7007:    bei Xamarin.Android.Tasks.FilterAssemblies.RunTask()
	error XAFLT7007:    bei Microsoft.Android.Build.Tasks.AndroidTask.Execute()

This happens because when System.Reflection.Metadata comes across an
Attribute which has a generic type parameter, it does *not* return a
[`TypeReferenceHandle`][1], but instead a
[`TypeSpecificationHandle`][2].

Update `MetadataExtensions.GetCustomAttributeFullName()` to support
[`HandleKind.TypeSpecification`][3]

[0]: https://learn.microsoft.com/dotnet/csharp/whats-new/csharp-11#generic-attributes
[1]: https://learn.microsoft.com/dotnet/api/system.reflection.metadata.typereferencehandle?view=net-8.0
[2]: https://learn.microsoft.com/dotnet/api/system.reflection.metadata.typespecificationhandle?view=net-8.0
[3]: https://learn.microsoft.com/dotnet/api/system.reflection.metadata.handlekind?view=net-8.0
@github-actions github-actions bot locked and limited conversation to collaborators Nov 8, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Area: App+Library Build Issues when building Library projects or Application projects. need-attention A xamarin-android contributor needs to review
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants