Browse Source

FIxing crash where a generic enum is passed into get_shared_type. Also added automated test to catch this scenario. (#12622)

Alex Thibodeau 6 years ago
parent
commit
d5dfaf6006
3 changed files with 49 additions and 1 deletions
  1. 2 0
      mono/mini/mini-generic-sharing.c
  2. 2 1
      mono/tests/Makefile.am
  3. 45 0
      mono/tests/async-generic-enum.cs

+ 2 - 0
mono/mini/mini-generic-sharing.c

@@ -3892,6 +3892,8 @@ get_shared_type (MonoType *t, MonoType *type)
 	ttype = type->type;
 	ttype = type->type;
 	if (type->type == MONO_TYPE_VALUETYPE) {
 	if (type->type == MONO_TYPE_VALUETYPE) {
 		ttype = mono_class_enum_basetype_internal (type->data.klass)->type;
 		ttype = mono_class_enum_basetype_internal (type->data.klass)->type;
+	} else if (type->type == MONO_TYPE_GENERICINST && m_class_is_enumtype(type->data.generic_class->container_class)) {
+		ttype = mono_class_enum_basetype_internal (mono_class_from_mono_type_internal (type))->type;
 	} else if (MONO_TYPE_IS_REFERENCE (type)) {
 	} else if (MONO_TYPE_IS_REFERENCE (type)) {
 		ttype = MONO_TYPE_OBJECT;
 		ttype = MONO_TYPE_OBJECT;
 	} else if (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) {
 	} else if (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) {

+ 2 - 1
mono/tests/Makefile.am

@@ -711,7 +711,8 @@ TESTS_CS_SRC=		\
 	generic-unmanaged-constraint.cs \
 	generic-unmanaged-constraint.cs \
 	bug-10834.cs \
 	bug-10834.cs \
 	bug-10837.cs	\
 	bug-10837.cs	\
-	bug-gh-9507.cs
+	bug-gh-9507.cs	\
+	async-generic-enum.cs
 
 
 # some tests fail to compile on mcs
 # some tests fail to compile on mcs
 if CSC_IS_ROSLYN
 if CSC_IS_ROSLYN

+ 45 - 0
mono/tests/async-generic-enum.cs

@@ -0,0 +1,45 @@
+using System;
+using System.Threading.Tasks;
+
+
+public enum someEnum2 {
+    aaa,
+    bbb
+}
+class Tests {
+    private static GenericEnumTest<someEnum2> test1 = new GenericEnumTest<someEnum2>();
+    public static async Task<int> Main(string[] args)
+    {
+        int retVal = await test1.ThrowExceptionWithGeneric(someEnum2.aaa);
+        return retVal;
+    }
+}
+
+public class GenericEnumTest<T> where T : struct {
+    public enum anEnum {
+        val1,
+        val2
+    }
+
+    public async Task<int> ThrowExceptionWithGeneric(T val) {
+        try {
+            await ThrowExceptionTaskReturn(val);
+        } catch (Exception e) {
+            Console.WriteLine(e);
+        }
+        return 0;
+    }
+
+    public async Task<anEnum> ThrowExceptionTaskReturn(T val) {
+        for (int i = 0; i < 3; i++) {
+            Console.WriteLine("[ASY] " + (3 - i) + " " + System.Threading.Thread.CurrentThread.ManagedThreadId);
+            await Task.Delay(TimeSpan.FromSeconds(1));
+        }
+
+        var nulla = default(string[]);
+        // Causes exception to fire, walking the stack trace causes nullpointer exception bug
+        var vala = nulla[0];
+
+        return anEnum.val1;
+    }
+}