Skip to content

Commit

Permalink
[mono] Do not ignore non-public custom attributes in dynamic assembli…
Browse files Browse the repository at this point in the history
…es (#87406)

Fixes #60650
  • Loading branch information
ivanpovazan committed Jun 22, 2023
1 parent 2f2aaae commit 4586587
Show file tree
Hide file tree
Showing 8 changed files with 234 additions and 61 deletions.
70 changes: 70 additions & 0 deletions src/libraries/System.Reflection.Emit/tests/AssemblyBuilderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,76 @@ public void SetCustomAttribute_CustomAttributeBuilder_NullAttributeBuilder_Throw
AssertExtensions.Throws<ArgumentNullException>("customBuilder", () => assembly.SetCustomAttribute(null));
}

[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsReflectionEmitSupported))]
public void SetCustomAttribute_GetCustomAttributesData_NonPublicVisibility_DefinedInternally()
{
AssemblyBuilder assembly = Helpers.DynamicAssembly();
ModuleBuilder module = assembly.DefineDynamicModule("DynamicModule");

TypeBuilder internalAttributeType = module.DefineType("DynamicInternalAttribute", TypeAttributes.NotPublic, typeof(Attribute));
ConstructorBuilder internalAttributeCtor = internalAttributeType.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new Type[0]);
internalAttributeCtor.GetILGenerator().Emit(OpCodes.Ret);

ConstructorInfo internalAttributeCtorInfo = internalAttributeType.CreateTypeInfo().GetConstructor(Array.Empty<Type>());
CustomAttributeBuilder customAttribute = new CustomAttributeBuilder(internalAttributeCtorInfo, Array.Empty<object>());

assembly.SetCustomAttribute(customAttribute);
Assert.Single(assembly.GetCustomAttributesData());
}

[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsReflectionEmitSupported))]
public void SetCustomAttribute_GetCustomAttributes_NonPublicVisibility_DefinedInternally()
{
AssemblyBuilder assembly = Helpers.DynamicAssembly();
ModuleBuilder module = assembly.DefineDynamicModule("DynamicModule");

TypeBuilder internalAttributeType = module.DefineType("DynamicInternalAttribute", TypeAttributes.NotPublic, typeof(Attribute));
ConstructorBuilder internalAttributeCtor = internalAttributeType.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new Type[0]);
internalAttributeCtor.GetILGenerator().Emit(OpCodes.Ret);

ConstructorInfo internalAttributeCtorInfo = internalAttributeType.CreateTypeInfo().GetConstructor(Array.Empty<Type>());
CustomAttributeBuilder customAttribute = new CustomAttributeBuilder(internalAttributeCtorInfo, Array.Empty<object>());

assembly.SetCustomAttribute(customAttribute);
Assert.Single(assembly.GetCustomAttributes(false));
}

[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsReflectionEmitSupported))]
public void SetCustomAttribute_GetCustomAttributesData_NonPublicVisibility_DefinedExternally()
{
AssemblyBuilder assembly1 = Helpers.DynamicAssembly();
ModuleBuilder module1 = assembly1.DefineDynamicModule("DynamicModule");
AssemblyBuilder assembly2 = Helpers.DynamicAssembly("AnotherTestAssembly");

TypeBuilder internalAttributeType = module1.DefineType("DynamicInternalAttribute", TypeAttributes.NotPublic, typeof(Attribute));
ConstructorBuilder internalAttributeCtor = internalAttributeType.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new Type[0]);
internalAttributeCtor.GetILGenerator().Emit(OpCodes.Ret);

ConstructorInfo internalAttributeCtorInfo = internalAttributeType.CreateTypeInfo().GetConstructor(Array.Empty<Type>());
CustomAttributeBuilder customAttribute = new CustomAttributeBuilder(internalAttributeCtorInfo, Array.Empty<object>());

assembly2.SetCustomAttribute(customAttribute);
Assert.Single(assembly2.GetCustomAttributesData());
}

[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsReflectionEmitSupported))]
public void SetCustomAttribute_GetCustomAttributes_NonPublicVisibility_DefinedExternally()
{
AssemblyBuilder assembly1 = Helpers.DynamicAssembly();
ModuleBuilder module1 = assembly1.DefineDynamicModule("DynamicModule");
AssemblyBuilder assembly2 = Helpers.DynamicAssembly("AnotherTestAssembly");

TypeBuilder internalAttributeType = module1.DefineType("DynamicInternalAttribute", TypeAttributes.NotPublic, typeof(Attribute));
ConstructorBuilder internalAttributeCtor = internalAttributeType.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new Type[0]);
internalAttributeCtor.GetILGenerator().Emit(OpCodes.Ret);

ConstructorInfo internalAttributeCtorInfo = internalAttributeType.CreateTypeInfo().GetConstructor(Array.Empty<Type>());
CustomAttributeBuilder customAttribute = new CustomAttributeBuilder(internalAttributeCtorInfo, Array.Empty<object>());

assembly2.SetCustomAttribute(customAttribute);
Assert.Empty(assembly2.GetCustomAttributes(false));
}

public static IEnumerable<object[]> Equals_TestData()
{
AssemblyBuilder assembly = Helpers.DynamicAssembly(name: "Name1");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,71 @@ public void SetCustomAttribute_CustomAttributeBuilder_NullBuilder_ThrowsArgument
ModuleBuilder module = Helpers.DynamicModule();
AssertExtensions.Throws<ArgumentNullException>("customBuilder", () => module.SetCustomAttribute(null));
}

[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsReflectionEmitSupported))]
public void SetCustomAttribute_GetCustomAttributesData_NonPublicVisibility_DefinedInternally()
{
ModuleBuilder module = Helpers.DynamicModule();

TypeBuilder internalAttributeType = module.DefineType("DynamicInternalAttribute", TypeAttributes.NotPublic, typeof(Attribute));
ConstructorBuilder internalAttributeCtor = internalAttributeType.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new Type[0]);
internalAttributeCtor.GetILGenerator().Emit(OpCodes.Ret);

ConstructorInfo internalAttributeCtorInfo = internalAttributeType.CreateTypeInfo().GetConstructor(Array.Empty<Type>());
CustomAttributeBuilder customAttribute = new CustomAttributeBuilder(internalAttributeCtorInfo, Array.Empty<object>());

module.SetCustomAttribute(customAttribute);
Assert.Single(module.GetCustomAttributesData());
}

[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsReflectionEmitSupported))]
public void SetCustomAttribute_GetCustomAttributes_NonPublicVisibility_DefinedInternally()
{
ModuleBuilder module = Helpers.DynamicModule();

TypeBuilder internalAttributeType = module.DefineType("DynamicInternalAttribute", TypeAttributes.NotPublic, typeof(Attribute));
ConstructorBuilder internalAttributeCtor = internalAttributeType.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new Type[0]);
internalAttributeCtor.GetILGenerator().Emit(OpCodes.Ret);

ConstructorInfo internalAttributeCtorInfo = internalAttributeType.CreateTypeInfo().GetConstructor(Array.Empty<Type>());
CustomAttributeBuilder customAttribute = new CustomAttributeBuilder(internalAttributeCtorInfo, Array.Empty<object>());

module.SetCustomAttribute(customAttribute);
Assert.Single(module.GetCustomAttributes(false));
}

[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsReflectionEmitSupported))]
public void SetCustomAttribute_GetCustomAttributesData_NonPublicVisibility_DefinedExternally()
{
ModuleBuilder module1 = Helpers.DynamicModule();
ModuleBuilder module2 = Helpers.DynamicModule("AnotherTestAssembly", "AnotherTestModule");

TypeBuilder internalAttributeType = module1.DefineType("DynamicInternalAttribute", TypeAttributes.NotPublic, typeof(Attribute));
ConstructorBuilder internalAttributeCtor = internalAttributeType.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new Type[0]);
internalAttributeCtor.GetILGenerator().Emit(OpCodes.Ret);

ConstructorInfo internalAttributeCtorInfo = internalAttributeType.CreateTypeInfo().GetConstructor(Array.Empty<Type>());
CustomAttributeBuilder customAttribute = new CustomAttributeBuilder(internalAttributeCtorInfo, Array.Empty<object>());

module2.SetCustomAttribute(customAttribute);
Assert.Single(module2.GetCustomAttributesData());
}

[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsReflectionEmitSupported))]
public void SetCustomAttribute_GetCustomAttributes_NonPublicVisibility_DefinedExternally()
{
ModuleBuilder module1 = Helpers.DynamicModule();
ModuleBuilder module2 = Helpers.DynamicModule("AnotherTestAssembly", "AnotherTestModule");

TypeBuilder internalAttributeType = module1.DefineType("DynamicInternalAttribute", TypeAttributes.NotPublic, typeof(Attribute));
ConstructorBuilder internalAttributeCtor = internalAttributeType.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new Type[0]);
internalAttributeCtor.GetILGenerator().Emit(OpCodes.Ret);

ConstructorInfo internalAttributeCtorInfo = internalAttributeType.CreateTypeInfo().GetConstructor(Array.Empty<Type>());
CustomAttributeBuilder customAttribute = new CustomAttributeBuilder(internalAttributeCtorInfo, Array.Empty<object>());

module2.SetCustomAttribute(customAttribute);
Assert.Empty(module2.GetCustomAttributes(false));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -854,33 +854,10 @@ public override bool IsDefined(Type attributeType, bool inherit)
return base.IsDefined(attributeType, inherit);
}

public override object[] GetCustomAttributes(bool inherit)
{
return GetCustomAttributes(null!, inherit); // FIXME: coreclr doesn't allow null attributeType
}

public override object[] GetCustomAttributes(Type attributeType, bool inherit)
{
if (cattrs == null || cattrs.Length == 0)
return Array.Empty<object>();

if (attributeType is TypeBuilder)
throw new InvalidOperationException(SR.InvalidOperation_CannotHaveFirstArgumentAsTypeBuilder);
public override object[] GetCustomAttributes(bool inherit) => CustomAttribute.GetCustomAttributes(this, inherit);

List<object> results = new List<object>();
for (int i = 0; i < cattrs.Length; i++)
{
Type t = cattrs[i].Ctor.GetType();

if (t is TypeBuilder)
throw new InvalidOperationException(SR.InvalidOperation_CannotConstructCustomAttributeForTypeBuilderType);

if (attributeType == null || attributeType.IsAssignableFrom(t))
results.Add(cattrs[i].Invoke());
}

return results.ToArray();
}
public override object[] GetCustomAttributes(Type attributeType, bool inherit) =>
CustomAttribute.GetCustomAttributes(this, attributeType, inherit);

public override IList<CustomAttributeData> GetCustomAttributesData()
{
Expand Down
2 changes: 1 addition & 1 deletion src/mono/mono/metadata/custom-attrs-internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ typedef struct _MonoDecodeCustomAttr {
} MonoDecodeCustomAttr;

MonoCustomAttrInfo*
mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs);
mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs, gboolean respect_cattr_visibility);

typedef gboolean (*MonoAssemblyMetadataCustomAttrIterFunc) (MonoImage *image, guint32 typeref_scope_token, const gchar* nspace, const gchar* name, guint32 method_token, guint32 *cols, gpointer user_data);

Expand Down
Loading

0 comments on commit 4586587

Please sign in to comment.