[interp] Fix enum constrained calls on netcore (#31618)
authorVlad Brezae <brezaevlad@gmail.com>
Mon, 3 Feb 2020 11:08:05 +0000 (03:08 -0800)
committerGitHub <noreply@github.com>
Mon, 3 Feb 2020 11:08:05 +0000 (03:08 -0800)
We were failing to dereference a managed pointer to the enum, due to incorrect checks, when doing a constrained call.

Fixes https://github.com/mono/mono/issues/18530

src/mono/mono/mini/interp/transform.c

index ad7154ef66b12b2dcca91e4fb23a06c35245ddec..be002146491eec5d2b6c7f5d1efb15b2fb1a2d88 100644 (file)
@@ -2193,8 +2193,14 @@ interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target
                        interp_add_ins (td, MINT_LDIND_I);
                        td->last_ins->data [0] = csignature->param_count;
                } else if (target_method->klass == mono_defaults.object_class || target_method->klass == m_class_get_parent (mono_defaults.enum_class) || target_method->klass == mono_defaults.enum_class) {
-                       if (target_method->klass == mono_defaults.enum_class && (td->sp - csignature->param_count - 1)->type == STACK_TYPE_MP) {
-                               /* managed pointer on the stack, we need to deref that puppy */
+                       /*
+                        * Constrained expects a managed pointer that normally needs dereferencing.
+                        * For value types that have their storage on the vtstack, a managed pointer
+                        * to it is identical to the internal pointer that is passed on the stack
+                        * when using the value type, not needing any dereferencing.
+                        */
+                       g_assert ((td->sp - csignature->param_count - 1)->type == STACK_TYPE_MP);
+                       if (mint_type (m_class_get_byval_arg (constrained_class)) != MINT_TYPE_VT) {
                                /* Always load the entire stackval, to handle also the case where the enum has long storage */
                                interp_add_ins (td, MINT_LDIND_I8);
                                td->last_ins->data [0] = csignature->param_count;
@@ -2209,7 +2215,8 @@ interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target
                                 * but that type doesn't override the method we're
                                 * calling, so we need to box `this'.
                                 */
-                               if (target_method->klass == mono_defaults.enum_class && (td->sp - csignature->param_count - 1)->type == STACK_TYPE_MP) {
+                               g_assert ((td->sp - csignature->param_count - 1)->type == STACK_TYPE_MP);
+                               if (mint_type (m_class_get_byval_arg (constrained_class)) != MINT_TYPE_VT) {
                                        /* managed pointer on the stack, we need to deref that puppy */
                                        /* Always load the entire stackval, to handle also the case where the enum has long storage */
                                        interp_add_ins (td, MINT_LDIND_I8);