From b1360afe0acf89893afce3ada862ce9480aa5a67 Mon Sep 17 00:00:00 2001 From: Vlad Brezae Date: Thu, 20 Apr 2017 15:01:30 +0300 Subject: [PATCH] [metadata] Lock around special static fields hash access If a type is loaded in another thread, the fields hash can get resized, leading to failure. --- mono/mini/jit-icalls.c | 11 +++++-- mono/tests/Makefile.am | 2 ++ mono/tests/generic-special2.2.cs | 54 ++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 3 deletions(-) create mode 100644 mono/tests/generic-special2.2.cs diff --git a/mono/mini/jit-icalls.c b/mono/mini/jit-icalls.c index b52edd4e404..401ac247e2a 100644 --- a/mono/mini/jit-icalls.c +++ b/mono/mini/jit-icalls.c @@ -888,11 +888,16 @@ mono_class_static_field_address (MonoDomain *domain, MonoClassField *field) //printf ("SFLDA1 %p\n", (char*)vtable->data + field->offset); - if (domain->special_static_fields && (addr = g_hash_table_lookup (domain->special_static_fields, field))) + if (field->offset == -1) { + /* Special static */ + g_assert (domain->special_static_fields); + mono_domain_lock (domain); + addr = g_hash_table_lookup (domain->special_static_fields, field); + mono_domain_unlock (domain); addr = mono_get_special_static_data (GPOINTER_TO_UINT (addr)); - else + } else { addr = (char*)mono_vtable_get_static_field_data (vtable) + field->offset; - + } return addr; } diff --git a/mono/tests/Makefile.am b/mono/tests/Makefile.am index 6b38d8d7e4b..10741f6d57c 100644 --- a/mono/tests/Makefile.am +++ b/mono/tests/Makefile.am @@ -344,6 +344,7 @@ TESTS_CS_SRC= \ generic-static-methods.2.cs \ generic-null-call.2.cs \ generic-special.2.cs \ + generic-special2.2.cs \ generic-exceptions.2.cs \ generic-virtual2.2.cs \ generic-valuetype-interface.2.cs \ @@ -616,6 +617,7 @@ TESTS_GSHARED_SRC = \ generic-tailcall2.2.cs \ generic-array-exc.2.cs \ generic-special.2.cs \ + generic-special2.2.cs \ generic-exceptions.2.cs \ generic-delegate2.2.cs \ generic-virtual2.2.cs \ diff --git a/mono/tests/generic-special2.2.cs b/mono/tests/generic-special2.2.cs new file mode 100644 index 00000000000..625d8736599 --- /dev/null +++ b/mono/tests/generic-special2.2.cs @@ -0,0 +1,54 @@ +using System; +using System.Reflection; +using System.IO; +using System.Collections.Generic; +using System.Threading; + +internal class GenericType { + [ThreadStatic] + internal static object static_var; + + public static void AccessStaticVar () + { + if (static_var != null && static_var.GetType () != typeof (List)) + throw new Exception ("Corrupted static var"); + GenericType.static_var = new List (); + } +} + +public static class Program { + private static bool stress; + + /* Create a lot of static vars */ + private static void CreateVTables () + { + Type[] nullArgs = new Type[0]; + Assembly ass = Assembly.GetAssembly (typeof (int)); + foreach (Type type in ass.GetTypes ()) { + try { + Type inst = typeof (GenericType<>).MakeGenericType (type); + Activator.CreateInstance (inst); + } catch { + } + } + } + + private static void StressStaticFieldAddr () + { + while (stress) { + GenericType.AccessStaticVar (); + } + } + + public static void Main (string[] args) + { + Thread thread = new Thread (StressStaticFieldAddr); + + stress = true; + thread.Start (); + CreateVTables (); + stress = false; + + thread.Join (); + } +} -- 2.25.1