Fix TPA map hash calculation. (#288)
authorMikhail Kurinnoi/AI Compiler Lab /SRR/Staff Engineer/Samsung Electronics <m.kurinnoi@samsung.com>
Thu, 25 Jun 2020 22:30:09 +0000 (01:30 +0300)
committer이형주/Common Platform Lab(SR)/Staff Engineer/삼성전자 <leee.lee@samsung.com>
Thu, 25 Jun 2020 22:30:09 +0000 (07:30 +0900)
* Fix TPA map hash calculation.

The point of issue is "the Turkish-I Problem". After locale changed, towupper() provide another result for "i" and different hash are calculated in case if file name have "i" letter.

* Regression test for #37910

src/binder/inc/applicationcontext.hpp
src/coreclr/tests/src/Loader/binding/assemblies/assemblybugs/37910/Ii.cs [new file with mode: 0644]
src/coreclr/tests/src/Loader/binding/assemblies/assemblybugs/37910/Ii.csproj [new file with mode: 0644]

index 83893f3..f315b32 100644 (file)
@@ -71,8 +71,12 @@ namespace BINDER_SPACE
             key = e.m_wszSimpleName;
             return key;
         }
-        static count_t Hash(const key_t &str) { return HashiString(str); }
-        static BOOL Equals(const key_t &lhs, const key_t &rhs) { LIMITED_METHOD_CONTRACT; return (_wcsicmp(lhs, rhs) == 0); }
+        static count_t Hash(const key_t &str)
+        {
+            SString ssKey(SString::Literal, str);
+            return ssKey.HashCaseInsensitive();
+        }
+        static BOOL Equals(const key_t &lhs, const key_t &rhs) { LIMITED_METHOD_CONTRACT; return (SString::_wcsicmp(lhs, rhs) == 0); }
         
         void OnDestructPerEntryCleanupAction(const SimpleNameToFileNameMapEntry & e)
         {
diff --git a/src/coreclr/tests/src/Loader/binding/assemblies/assemblybugs/37910/Ii.cs b/src/coreclr/tests/src/Loader/binding/assemblies/assemblybugs/37910/Ii.cs
new file mode 100644 (file)
index 0000000..65f0ea6
--- /dev/null
@@ -0,0 +1,39 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+using System;
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+public class Program
+{
+    [DllImport("libc", EntryPoint = "setlocale")]
+    public static extern IntPtr setlocale(int category, [MarshalAs(UnmanagedType.LPStr)] string locale);
+
+    public static int Main()
+    {
+        Assembly a1 = Assembly.GetExecutingAssembly();
+
+        // In case of Turkish locale:
+        // towupper 'i' -> \x0130 (instead of 'I')
+        // towlower 'I' -> \x0131 (instead of 'i')
+        const string TRLocale = "tr_TR.UTF-8";
+        IntPtr res = setlocale(6 /*LC_ALL*/, TRLocale);
+        if (TRLocale != Marshal.PtrToStringAnsi(res))
+        {
+            Console.WriteLine("Failed! " + TRLocale + " locale was not found in system!");
+            return -1;
+        }
+
+        Assembly a2 = Assembly.Load("Ii");
+
+        if (a1 != a2)
+        {
+            Console.WriteLine("Failed!");
+            return -2;
+        }
+
+        Console.WriteLine("Passed!");
+        return 100;
+    }
+}
diff --git a/src/coreclr/tests/src/Loader/binding/assemblies/assemblybugs/37910/Ii.csproj b/src/coreclr/tests/src/Loader/binding/assemblies/assemblybugs/37910/Ii.csproj
new file mode 100644 (file)
index 0000000..d1d1441
--- /dev/null
@@ -0,0 +1,12 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <CLRTestKind>BuildAndRun</CLRTestKind>
+    <CLRTestPriority>1</CLRTestPriority>
+    <!-- Test unsupported outside of linux -->
+    <CLRTestTargetUnsupported Condition="'$(TargetOS)' != 'Linux'">true</CLRTestTargetUnsupported>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="Ii.cs" />
+  </ItemGroup>
+</Project>