Skip to content

Mono ignores non-public custom attributes in dynamic assemblies #60650

@elinor-fung

Description

@elinor-fung

Description

When building a dynamic assembly via reflection with the various *Builder classes, non-public attributes are explicitly ignored in mono.

In mono_custom_attrs_from_builders_handle:

for (int i = 0; i < count; ++i) {
MONO_HANDLE_ARRAY_GETREF (cattr, cattrs, i);
if (!custom_attr_visible (image, cattr, ctor_handle, &ctor_method))
continue;

There's a comment about it matching .NET, but that is not what I see with coreclr or .NET Framework.

/* Skip nonpublic attributes since MS.NET seems to do the same */

Not sure if there's another reason mono skips non-public attributes?

Reproduction Steps

Dynamic assembly with an assembly-level non-public attribute:

AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("DynamicAssembly"), AssemblyBuilderAccess.Run);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("DynamicModule");

// Create internal attribute
TypeBuilder typeBuilder = moduleBuilder.DefineType("InternalAttribute", TypeAttributes.NotPublic, typeof(Attribute));
ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new Type[0]);
constructorBuilder.GetILGenerator().Emit(OpCodes.Ret);

// Add assembly-level attribute
ConstructorInfo constructorInfo = typeBuilder.CreateTypeInfo().GetConstructor(Array.Empty<Type>());
CustomAttributeBuilder customAttributeBuilder = new CustomAttributeBuilder(constructorInfo, Array.Empty<object>());
assemblyBuilder.SetCustomAttribute(customAttributeBuilder);

IList<CustomAttributeData> attrs = assemblyBuilder.GetCustomAttributesData();
Console.WriteLine($"{assemblyBuilder.GetName().Name} - Attributes (count: {attrs.Count})");
foreach (CustomAttributeData attr in attrs)
{
    Console.WriteLine($"  {attr}");
}

Expected behavior

The internal attribute is listed. On coreclr (and also .NET Framework 4.6.2), the above prints:

DynamicAssembly - Attributes (count: 1)
  [InternalAttribute()]

Actual behavior

The internal attribute is not listed. On mono, the above prints:

DynamicAssembly - Attributes (count: 0)

Other information

This results in the test infrastructure for Roslyn analyzers (in dotnet/roslyn-sdk) being unable to run on mono.

https://github.com/dotnet/roslyn-sdk/blob/27fe3d6060150031b532cc7255259c40a37a5fda/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerInfo.cs

They rely on emitting a non-public IgnoresAccessChecksToAttribute to skip access checks. Since mono ends up ignoring the attribute, using their test infrastructure results in:

System.MethodAccessException : Method `Microsoft.CodeAnalysis.Testing.AnalyzerInfo+CustomAnalysisContext..ctor()' is inaccessible from method `CustomAnalysisContextImpl..ctor()'
    Stack Trace:
        at CustomAnalysisContextImpl..ctor()

cc @lambdageek

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions