diff --git a/src/libraries/System.Reflection/tests/CustomAttributeTests.cs b/src/libraries/System.Reflection/tests/CustomAttributeTests.cs index bb9c928b542203..6b102884c0d2ca 100644 --- a/src/libraries/System.Reflection/tests/CustomAttributeTests.cs +++ b/src/libraries/System.Reflection/tests/CustomAttributeTests.cs @@ -76,5 +76,58 @@ public void AttributeWithDifferentPropertyTypes() Assert.Equal(1, attr.ObjectArray.Length); Assert.Null(attr.StringArray); } + + public class StringValuedAttribute : Attribute + { + public StringValuedAttribute (string s) + { + NamedField = s; + } + public StringValuedAttribute () {} + public string NamedProperty + { + get => NamedField; + set { NamedField = value; } + } + public string NamedField; + } + + internal class ClassWithAttrs + { + [StringValuedAttribute("")] + public void M1() {} + + [StringValuedAttribute(NamedProperty = "")] + public void M2() {} + + [StringValuedAttribute(NamedField = "")] + public void M3() {} + } + + [Fact] + public void StringAttributeValueRefEqualsStringEmpty () { + StringValuedAttribute attr; + attr = typeof (ClassWithAttrs).GetMethod("M1") + .GetCustomAttributes(typeof(StringValuedAttribute), true) + .Cast() + .Single(); + + Assert.Same(string.Empty, attr.NamedField); + + attr = typeof (ClassWithAttrs).GetMethod("M2") + .GetCustomAttributes(typeof(StringValuedAttribute), true) + .Cast() + .Single(); + + Assert.Same(string.Empty, attr.NamedField); + + + attr = typeof (ClassWithAttrs).GetMethod("M3") + .GetCustomAttributes(typeof(StringValuedAttribute), true) + .Cast() + .Single(); + + Assert.Same(string.Empty, attr.NamedField); + } } } diff --git a/src/mono/mono/metadata/custom-attrs.c b/src/mono/mono/metadata/custom-attrs.c index 48571da6a085ea..29c64c48f3fafc 100644 --- a/src/mono/mono/metadata/custom-attrs.c +++ b/src/mono/mono/metadata/custom-attrs.c @@ -397,7 +397,11 @@ MONO_RESTORE_WARNING // to decode some attributes in assemblies that Windows .NET Framework // and CoreCLR both manage to decode. // See https://simonsapin.github.io/wtf-8/ for a description of wtf-8. - *out_obj = (MonoObject*)mono_string_new_wtf8_len_checked (p, slen, error); + // Always use string.Empty for empty strings + if (slen == 0) + *out_obj = (MonoObject*)mono_string_empty_internal (mono_domain_get ()); + else + *out_obj = (MonoObject*)mono_string_new_wtf8_len_checked (p, slen, error); return NULL; } case MONO_TYPE_CLASS: {