From 39c49054a5e29bc442c16c6c9305ebaaf8c20c8b Mon Sep 17 00:00:00 2001 From: Fan Yang <52458914+fanyang-mono@users.noreply.github.com> Date: Thu, 13 Jun 2024 20:52:41 -0400 Subject: [PATCH] [mono] Fix assembly name parser to accommodate non-ASCII UTF8 strings (#103363) Fixes #103276 Added an automated test that the testcase failed in the above issue. It now passes with this change. Ideally, Mono should share the same assembly name parsing logic as CoreCLR, which is `AssemblyNameParser.TryParse`. --- .../tests/System.Reflection.Tests/GetTypeTests.cs | 8 ++++++++ .../Hello\345\267\245\347\250\213123.cs" | 8 ++++++++ .../Hello\345\267\245\347\250\213123.csproj" | 8 ++++++++ .../System.Reflection.Tests.csproj | 2 ++ src/mono/mono/eglib/eglib-remap.h | 1 + src/mono/mono/eglib/glib.h | 1 + src/mono/mono/eglib/gutf8.c | 8 ++++---- src/mono/mono/metadata/reflection.c | 15 ++++++++++++--- 8 files changed, 44 insertions(+), 7 deletions(-) create mode 100644 "src/libraries/System.Runtime/tests/System.Reflection.Tests/Hello\345\267\245\347\250\213123/Hello\345\267\245\347\250\213123.cs" create mode 100644 "src/libraries/System.Runtime/tests/System.Reflection.Tests/Hello\345\267\245\347\250\213123/Hello\345\267\245\347\250\213123.csproj" diff --git a/src/libraries/System.Runtime/tests/System.Reflection.Tests/GetTypeTests.cs b/src/libraries/System.Runtime/tests/System.Reflection.Tests/GetTypeTests.cs index ba1cb8a203c4c..b034a56c0972f 100644 --- a/src/libraries/System.Runtime/tests/System.Reflection.Tests/GetTypeTests.cs +++ b/src/libraries/System.Runtime/tests/System.Reflection.Tests/GetTypeTests.cs @@ -300,6 +300,14 @@ public void TestTypeIdentifierAttribute() Assert.Equal(42, mi.Invoke(null, args)); } + [Fact] + public void TestAssemblyNameWithInternationalChar() + { + Type testObj = typeof(Hello工程123.Program); + var t = Type.GetType(testObj.AssemblyQualifiedName); + Assert.NotNull(t); + } + [Fact] public void IgnoreLeadingDotForTypeNamesWithoutNamespace() { diff --git "a/src/libraries/System.Runtime/tests/System.Reflection.Tests/Hello\345\267\245\347\250\213123/Hello\345\267\245\347\250\213123.cs" "b/src/libraries/System.Runtime/tests/System.Reflection.Tests/Hello\345\267\245\347\250\213123/Hello\345\267\245\347\250\213123.cs" new file mode 100644 index 0000000000000..64ac6b4c7c059 --- /dev/null +++ "b/src/libraries/System.Runtime/tests/System.Reflection.Tests/Hello\345\267\245\347\250\213123/Hello\345\267\245\347\250\213123.cs" @@ -0,0 +1,8 @@ +using System; + +namespace System.Reflection.Hello工程123 +{ + public class Program + { + } +} \ No newline at end of file diff --git "a/src/libraries/System.Runtime/tests/System.Reflection.Tests/Hello\345\267\245\347\250\213123/Hello\345\267\245\347\250\213123.csproj" "b/src/libraries/System.Runtime/tests/System.Reflection.Tests/Hello\345\267\245\347\250\213123/Hello\345\267\245\347\250\213123.csproj" new file mode 100644 index 0000000000000..f5e314a6ef200 --- /dev/null +++ "b/src/libraries/System.Runtime/tests/System.Reflection.Tests/Hello\345\267\245\347\250\213123/Hello\345\267\245\347\250\213123.csproj" @@ -0,0 +1,8 @@ + + + $(NetCoreAppCurrent) + + + + + \ No newline at end of file diff --git a/src/libraries/System.Runtime/tests/System.Reflection.Tests/System.Reflection.Tests.csproj b/src/libraries/System.Runtime/tests/System.Reflection.Tests/System.Reflection.Tests.csproj index 9c380a90bfbd2..a5cf23579908e 100644 --- a/src/libraries/System.Runtime/tests/System.Reflection.Tests/System.Reflection.Tests.csproj +++ b/src/libraries/System.Runtime/tests/System.Reflection.Tests/System.Reflection.Tests.csproj @@ -77,6 +77,7 @@ + @@ -87,5 +88,6 @@ <__ExcludeFromBundle Include="TestAssembly.dll" /> + <__ExcludeFromBundle Include="Hello工程123.dll" /> diff --git a/src/mono/mono/eglib/eglib-remap.h b/src/mono/mono/eglib/eglib-remap.h index 3f42bd8308afc..1834554d8b177 100644 --- a/src/mono/mono/eglib/eglib-remap.h +++ b/src/mono/mono/eglib/eglib-remap.h @@ -219,6 +219,7 @@ #define g_wtf8_to_utf16 monoeg_g_wtf8_to_utf16 #define g_utf8_to_utf16_custom_alloc monoeg_g_utf8_to_utf16_custom_alloc #define g_utf8_to_utf16le_custom_alloc monoeg_g_utf8_to_utf16le_custom_alloc +#define g_utf8_validate_part monoeg_g_utf8_validate_part #define g_utf8_validate monoeg_g_utf8_validate #define g_vasprintf monoeg_g_vasprintf #define g_assertion_disable_global monoeg_assertion_disable_global diff --git a/src/mono/mono/eglib/glib.h b/src/mono/mono/eglib/glib.h index ae0dd994db235..0471f98f71786 100644 --- a/src/mono/mono/eglib/glib.h +++ b/src/mono/mono/eglib/glib.h @@ -1067,6 +1067,7 @@ g_async_safe_printf (gchar const *format, ...) */ extern const guchar g_utf8_jump_table[256]; +gboolean g_utf8_validate_part (const unsigned char *inptr, size_t len); gboolean g_utf8_validate (const gchar *str, gssize max_len, const gchar **end); glong g_utf8_strlen (const gchar *str, gssize max); diff --git a/src/mono/mono/eglib/gutf8.c b/src/mono/mono/eglib/gutf8.c index 569d55fa3bd66..1fa83d08dbaca 100644 --- a/src/mono/mono/eglib/gutf8.c +++ b/src/mono/mono/eglib/gutf8.c @@ -30,8 +30,8 @@ const guchar g_utf8_jump_table[256] = { 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, 4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1 }; -static gboolean -utf8_validate (const unsigned char *inptr, size_t len) +gboolean +g_utf8_validate_part (const unsigned char *inptr, size_t len) { const unsigned char *ptr = inptr + len; unsigned char c; @@ -105,7 +105,7 @@ g_utf8_validate (const gchar *str, gssize max_len, const gchar **end) if (max_len < 0) { while (*inptr != 0) { length = g_utf8_jump_table[*inptr]; - if (!utf8_validate (inptr, length)) { + if (!g_utf8_validate_part (inptr, length)) { valid = FALSE; break; } @@ -124,7 +124,7 @@ g_utf8_validate (const gchar *str, gssize max_len, const gchar **end) length = g_utf8_jump_table[*inptr]; min = MIN (length, GSSIZE_TO_UINT (max_len - n)); - if (!utf8_validate (inptr, min)) { + if (!g_utf8_validate_part (inptr, min)) { valid = FALSE; break; } diff --git a/src/mono/mono/metadata/reflection.c b/src/mono/mono/metadata/reflection.c index 1539b020a1b6b..70e114a191999 100644 --- a/src/mono/mono/metadata/reflection.c +++ b/src/mono/mono/metadata/reflection.c @@ -1548,8 +1548,17 @@ assembly_name_to_aname (MonoAssemblyName *assembly, char *p) } assembly->name = p; s = p; - while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p))) - p++; + guchar *inptr = (guchar *) p; + while (*p && (*p != ',') && (*p != '\0')) { + if (quoted && (*p == '"')) + break; + guint length = g_utf8_jump_table[*inptr]; + if (!g_utf8_validate_part (inptr, length)) { + return 0; + } + p += length; + inptr += length; + } if (quoted) { if (*p != '"') return 1; @@ -1648,7 +1657,7 @@ assembly_name_to_aname (MonoAssemblyName *assembly, char *p) found_sep = 1; continue; } - /* failed */ + /* Done processing */ if (!found_sep) return 1; }