From c5dc589e6cc09a8da131a632160c8b6f047a35a2 Mon Sep 17 00:00:00 2001 From: Medha Tiwari Date: Sun, 20 Jul 2025 20:22:50 +0200 Subject: [PATCH 1/5] Fix System.Object.GetCustomAttributes() returning extra internal attributes on Mono --- src/mono/mono/metadata/custom-attrs.c | 51 +++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/src/mono/mono/metadata/custom-attrs.c b/src/mono/mono/metadata/custom-attrs.c index 8bb0fb414a235d..c0f5a629a2623d 100644 --- a/src/mono/mono/metadata/custom-attrs.c +++ b/src/mono/mono/metadata/custom-attrs.c @@ -1822,6 +1822,36 @@ cattr_class_match (MonoClass *attr_klass, MonoClass *klass) (m_class_is_gtd (attr_klass) && m_class_is_ginst (klass) && mono_class_is_assignable_from_internal (attr_klass, mono_class_get_generic_type_definition (klass))); } +/* + * Helper function to filter out internal/compiler-generated attributes + * that should not be visible through reflection to match CoreCLR behavior + */ +static gboolean +should_filter_attribute_for_reflection (MonoMethod *ctor) +{ + MonoClass *attr_class = ctor->klass; + const char *attr_name = m_class_get_name (attr_class); + const char *attr_namespace = m_class_get_name_space (attr_class); + + // Filter out these specific attributes from System.Object reflection + if (strcmp (attr_namespace, "System.Runtime.CompilerServices") == 0) { + if (strcmp (attr_name, "NullableContextAttribute") == 0 || + strcmp (attr_name, "TypeForwardedFromAttribute") == 0 || + strcmp (attr_name, "IsReadOnlyAttribute") == 0) { + return TRUE; + } + } + + if (strcmp (attr_namespace, "System.Runtime.InteropServices") == 0) { + if (strcmp (attr_name, "ClassInterfaceAttribute") == 0 || + strcmp (attr_name, "ComVisibleAttribute") == 0) { + return TRUE; + } + } + + return FALSE; +} + static MonoArrayHandle mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error) { @@ -1847,11 +1877,24 @@ mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_ for (i = 0; i < cinfo->num_attrs; ++i) { MonoMethod *ctor = cinfo->attrs[i].ctor; g_assert (ctor); - if (cattr_class_match (attr_klass, ctor->klass)) + if (cattr_class_match (attr_klass, ctor->klass)) { + // Apply filtering for System.Object attributes + if (should_filter_attribute_for_reflection (ctor)) { + continue; // Skip this attribute + } n++; + } } } else { - n = cinfo->num_attrs; + // Count attributes while applying filtering + for (i = 0; i < cinfo->num_attrs; ++i) { + MonoMethod *ctor = cinfo->attrs[i].ctor; + g_assert (ctor); + // Apply filtering for System.Object attributes + if (!should_filter_attribute_for_reflection (ctor)) { + n++; + } + } } result = mono_array_new_cached_handle (mono_defaults.attribute_class, n, error); @@ -1860,6 +1903,10 @@ mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_ for (i = 0; i < cinfo->num_attrs; ++i) { MonoCustomAttrEntry *centry = &cinfo->attrs [i]; if (!attr_klass || cattr_class_match (attr_klass, centry->ctor->klass)) { + // Apply filtering for System.Object attributes + if (should_filter_attribute_for_reflection (centry->ctor)) { + continue; // Skip this attribute + } create_custom_attr_into_array (cinfo->image, centry->ctor, centry->data, centry->data_size, result, n, error); goto_if_nok (error, exit); From d97eb3890f1240fbfa558d6b3a96f6ec2eda95f1 Mon Sep 17 00:00:00 2001 From: Medha Tiwari Date: Wed, 23 Jul 2025 00:18:07 +0200 Subject: [PATCH 2/5] Fix System.Object GetCustomAttributes inherit parameter inconsistency --- .../System/Reflection/RuntimeCustomAttributeData.cs | 2 +- .../System.Reflection.Tests/CustomAttributeTests.cs | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs index eab9a97e8ba8e4..2cd056338220fc 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs @@ -1270,7 +1270,7 @@ internal static object[] GetCustomAttributes(RuntimeType type, RuntimeType caTyp for (int i = 0; i < pcas.Count; i++) result.Add(pcas[i]); - while (type != (RuntimeType)typeof(object) && type != null) + while (type != null) { AddCustomAttributes(ref result, type.GetRuntimeModule(), type.MetadataToken, caType, mustBeInheritable, result); mustBeInheritable = true; diff --git a/src/libraries/System.Runtime/tests/System.Reflection.Tests/CustomAttributeTests.cs b/src/libraries/System.Runtime/tests/System.Reflection.Tests/CustomAttributeTests.cs index c3c7f3c465e413..efbea3bc4413fe 100644 --- a/src/libraries/System.Runtime/tests/System.Reflection.Tests/CustomAttributeTests.cs +++ b/src/libraries/System.Runtime/tests/System.Reflection.Tests/CustomAttributeTests.cs @@ -275,5 +275,15 @@ public void BoxedEnumAttributes() Assert.Equal(typeof(EnumForArrays[]), att.B3.GetType()); Assert.Equal(EnumForArrays.Two, ((EnumForArrays[])att.B3)[0]); } + + + [Fact] + public void SystemObject_GetCustomAttributes_InheritanceConsistency() + { + Type objectType = typeof(object); + object[] attributesWithoutInherit = objectType.GetCustomAttributes(inherit: false); + object[] attributesWithInherit = objectType.GetCustomAttributes(inherit: true); + Assert.Equal(attributesWithoutInherit.Length, attributesWithInherit.Length); + } } } From 4f318e7d89d4eae99fc73cc97ea50a64d84859ae Mon Sep 17 00:00:00 2001 From: Medha Tiwari Date: Wed, 23 Jul 2025 00:21:01 +0200 Subject: [PATCH 3/5] Revert "Fix System.Object.GetCustomAttributes() returning extra internal attributes on Mono" This reverts commit c5dc589e6cc09a8da131a632160c8b6f047a35a2. --- src/mono/mono/metadata/custom-attrs.c | 51 ++------------------------- 1 file changed, 2 insertions(+), 49 deletions(-) diff --git a/src/mono/mono/metadata/custom-attrs.c b/src/mono/mono/metadata/custom-attrs.c index c0f5a629a2623d..8bb0fb414a235d 100644 --- a/src/mono/mono/metadata/custom-attrs.c +++ b/src/mono/mono/metadata/custom-attrs.c @@ -1822,36 +1822,6 @@ cattr_class_match (MonoClass *attr_klass, MonoClass *klass) (m_class_is_gtd (attr_klass) && m_class_is_ginst (klass) && mono_class_is_assignable_from_internal (attr_klass, mono_class_get_generic_type_definition (klass))); } -/* - * Helper function to filter out internal/compiler-generated attributes - * that should not be visible through reflection to match CoreCLR behavior - */ -static gboolean -should_filter_attribute_for_reflection (MonoMethod *ctor) -{ - MonoClass *attr_class = ctor->klass; - const char *attr_name = m_class_get_name (attr_class); - const char *attr_namespace = m_class_get_name_space (attr_class); - - // Filter out these specific attributes from System.Object reflection - if (strcmp (attr_namespace, "System.Runtime.CompilerServices") == 0) { - if (strcmp (attr_name, "NullableContextAttribute") == 0 || - strcmp (attr_name, "TypeForwardedFromAttribute") == 0 || - strcmp (attr_name, "IsReadOnlyAttribute") == 0) { - return TRUE; - } - } - - if (strcmp (attr_namespace, "System.Runtime.InteropServices") == 0) { - if (strcmp (attr_name, "ClassInterfaceAttribute") == 0 || - strcmp (attr_name, "ComVisibleAttribute") == 0) { - return TRUE; - } - } - - return FALSE; -} - static MonoArrayHandle mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error) { @@ -1877,24 +1847,11 @@ mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_ for (i = 0; i < cinfo->num_attrs; ++i) { MonoMethod *ctor = cinfo->attrs[i].ctor; g_assert (ctor); - if (cattr_class_match (attr_klass, ctor->klass)) { - // Apply filtering for System.Object attributes - if (should_filter_attribute_for_reflection (ctor)) { - continue; // Skip this attribute - } + if (cattr_class_match (attr_klass, ctor->klass)) n++; - } } } else { - // Count attributes while applying filtering - for (i = 0; i < cinfo->num_attrs; ++i) { - MonoMethod *ctor = cinfo->attrs[i].ctor; - g_assert (ctor); - // Apply filtering for System.Object attributes - if (!should_filter_attribute_for_reflection (ctor)) { - n++; - } - } + n = cinfo->num_attrs; } result = mono_array_new_cached_handle (mono_defaults.attribute_class, n, error); @@ -1903,10 +1860,6 @@ mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_ for (i = 0; i < cinfo->num_attrs; ++i) { MonoCustomAttrEntry *centry = &cinfo->attrs [i]; if (!attr_klass || cattr_class_match (attr_klass, centry->ctor->klass)) { - // Apply filtering for System.Object attributes - if (should_filter_attribute_for_reflection (centry->ctor)) { - continue; // Skip this attribute - } create_custom_attr_into_array (cinfo->image, centry->ctor, centry->data, centry->data_size, result, n, error); goto_if_nok (error, exit); From 98554b60ca128fbb02990845effa723f61787a59 Mon Sep 17 00:00:00 2001 From: Medha Tiwari Date: Wed, 23 Jul 2025 00:36:10 +0200 Subject: [PATCH 4/5] remove extra line --- .../tests/System.Reflection.Tests/CustomAttributeTests.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libraries/System.Runtime/tests/System.Reflection.Tests/CustomAttributeTests.cs b/src/libraries/System.Runtime/tests/System.Reflection.Tests/CustomAttributeTests.cs index efbea3bc4413fe..e850c30f723a14 100644 --- a/src/libraries/System.Runtime/tests/System.Reflection.Tests/CustomAttributeTests.cs +++ b/src/libraries/System.Runtime/tests/System.Reflection.Tests/CustomAttributeTests.cs @@ -276,7 +276,6 @@ public void BoxedEnumAttributes() Assert.Equal(EnumForArrays.Two, ((EnumForArrays[])att.B3)[0]); } - [Fact] public void SystemObject_GetCustomAttributes_InheritanceConsistency() { From 6bf83a1fa4b910dac1d112fcd4b8f738a37b9b30 Mon Sep 17 00:00:00 2001 From: Medha Tiwari Date: Wed, 23 Jul 2025 01:17:09 +0200 Subject: [PATCH 5/5] Use do-while loop to include System.Object attributes Signed-off-by: Medha Tiwari --- .../src/System/Reflection/RuntimeCustomAttributeData.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs index 2cd056338220fc..f92173602ebca0 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs @@ -1270,12 +1270,12 @@ internal static object[] GetCustomAttributes(RuntimeType type, RuntimeType caTyp for (int i = 0; i < pcas.Count; i++) result.Add(pcas[i]); - while (type != null) + do { AddCustomAttributes(ref result, type.GetRuntimeModule(), type.MetadataToken, caType, mustBeInheritable, result); mustBeInheritable = true; type = (type.BaseType as RuntimeType)!; - } + } while (type != (RuntimeType)typeof(object) && type != null); object[] typedResult = CreateAttributeArrayHelper(caType, result.Count); for (int i = 0; i < result.Count; i++)