diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/CustomAttribute.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/CustomAttribute.cs
index 049a06bd0817c5..00abf6c9cfddcb 100644
--- a/src/mono/System.Private.CoreLib/src/System/Reflection/CustomAttribute.cs
+++ b/src/mono/System.Private.CoreLib/src/System/Reflection/CustomAttribute.cs
@@ -136,6 +136,14 @@ internal static object[] GetCustomAttributesBase(ICustomAttributeProvider obj, T
return attrs;
}
+ private static bool AttrTypeMatches(Type? attributeType, Type attrType)
+ {
+ if (attributeType == null)
+ return true;
+ return attributeType.IsAssignableFrom(attrType) ||
+ (attributeType.IsGenericTypeDefinition && attrType.IsGenericType && attributeType.IsAssignableFrom(attrType.GetGenericTypeDefinition()));
+ }
+
internal static object[] GetCustomAttributes(ICustomAttributeProvider obj, Type attributeType, bool inherit)
{
ArgumentNullException.ThrowIfNull(obj);
@@ -160,7 +168,7 @@ internal static object[] GetCustomAttributes(ICustomAttributeProvider obj, Type
if (res[0] == null)
throw new CustomAttributeFormatException("Invalid custom attribute format");
- if (attributeType != null)
+ if (attributeType != null && !attributeType.IsGenericTypeDefinition)
{
if (attributeType.IsAssignableFrom(res[0].GetType()))
{
@@ -219,13 +227,11 @@ internal static object[] GetCustomAttributes(ICustomAttributeProvider obj, Type
if (attr == null)
throw new CustomAttributeFormatException("Invalid custom attribute format");
- Type attrType = attr.GetType();
- if (attributeType != null && !attributeType.IsAssignableFrom(attrType))
- continue;
- a.Add(attr);
+ if (AttrTypeMatches(attributeType, attr.GetType()))
+ a.Add(attr);
}
- if (attributeType == null || attributeType.IsValueType)
+ if (attributeType == null || attributeType.IsValueType || attributeType.IsGenericTypeDefinition)
array = new Attribute[a.Count];
else
array = (Array.CreateInstance(attributeType, a.Count) as object[])!;
@@ -247,11 +253,8 @@ internal static object[] GetCustomAttributes(ICustomAttributeProvider obj, Type
throw new CustomAttributeFormatException("Invalid custom attribute format");
Type attrType = attr.GetType();
- if (attributeType != null)
- {
- if (!attributeType.IsAssignableFrom(attrType))
- continue;
- }
+ if (!AttrTypeMatches(attributeType, attr.GetType()))
+ continue;
AttributeInfo? firstAttribute;
if (attributeInfos.TryGetValue(attrType, out firstAttribute))
@@ -284,7 +287,7 @@ internal static object[] GetCustomAttributes(ICustomAttributeProvider obj, Type
}
} while (btype != null);
- if (attributeType == null || attributeType.IsValueType)
+ if (attributeType == null || attributeType.IsValueType || attributeType.IsGenericTypeDefinition)
array = new Attribute[a.Count];
else
array = (Array.CreateInstance(attributeType, a.Count) as object[])!;
diff --git a/src/mono/mono/metadata/custom-attrs.c b/src/mono/mono/metadata/custom-attrs.c
index 2bce3b3e79781c..d8fda30d4ce6eb 100644
--- a/src/mono/mono/metadata/custom-attrs.c
+++ b/src/mono/mono/metadata/custom-attrs.c
@@ -1770,6 +1770,13 @@ create_custom_attr_data_into_array (MonoImage *image, MonoCustomAttrEntry *cattr
HANDLE_FUNCTION_RETURN ();
}
+static gboolean
+cattr_class_match (MonoClass *attr_klass, MonoClass *klass)
+{
+ return mono_class_is_assignable_from_internal (attr_klass, 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)));
+}
+
static MonoArrayHandle
mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
{
@@ -1795,7 +1802,7 @@ 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 (mono_class_is_assignable_from_internal (attr_klass, ctor->klass))
+ if (cattr_class_match (attr_klass, ctor->klass))
n++;
}
} else {
@@ -1807,7 +1814,7 @@ mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_
n = 0;
for (i = 0; i < cinfo->num_attrs; ++i) {
MonoCustomAttrEntry *centry = &cinfo->attrs [i];
- if (!attr_klass || mono_class_is_assignable_from_internal (attr_klass, centry->ctor->klass)) {
+ if (!attr_klass || cattr_class_match (attr_klass, centry->ctor->klass)) {
create_custom_attr_into_array (cinfo->image, centry->ctor, centry->data,
centry->data_size, result, n, error);
goto_if_nok (error, exit);
@@ -2689,10 +2696,31 @@ custom_attr_class_name_from_method_token (MonoImage *image, guint32 method_token
if (assembly_token)
*assembly_token = 0;
return custom_attr_class_name_from_methoddef (image, methoddef_token, nspace, class_name);
+ } else if (class_index == MONO_MEMBERREF_PARENT_TYPESPEC) {
+ ERROR_DECL (error);
+
+ if (!image->assembly)
+ /* Avoid recursive calls from mono_assembly_has_reference_assembly_attribute () etc. */
+ return FALSE;
+
+ guint32 token = MONO_TOKEN_TYPE_SPEC | nindex;
+ MonoType *type = mono_type_get_checked (image, token, NULL, error);
+ if (!is_ok (error)) {
+ mono_error_cleanup (error);
+ return FALSE;
+ }
+
+ MonoClass *klass = mono_class_from_mono_type_internal (type);
+ g_assert (klass);
+ if (class_name)
+ *class_name = m_class_get_name (klass);
+ if (nspace)
+ *nspace = m_class_get_name_space (klass);
+ if (assembly_token)
+ *assembly_token = 0;
+ return TRUE;
} else {
- /* Attributes can't be generic, so it won't be
- * a typespec, and they're always
- * constructors, so it won't be a moduleref */
+ /* Attributes are always constructors, so it won't be a moduleref */
g_assert_not_reached ();
}
} else {
diff --git a/src/tests/issues.targets b/src/tests/issues.targets
index f39b00887245ec..6088017275f910 100644
--- a/src/tests/issues.targets
+++ b/src/tests/issues.targets
@@ -1360,9 +1360,6 @@
https://github.com/dotnet/runtime/issues/71656
-
- https://github.com/dotnet/runtime/issues/56887
-
https://github.com/dotnet/runtime/issues/54176
@@ -4049,4 +4046,4 @@
Condition="'%(ExcludeList.Extension)' == '.OutOfProcessTest'" />
-
\ No newline at end of file
+