[runtime] Fix byref out marshalling of arrays with a size parameter. Fixes #27614.
authorZoltan Varga <vargaz@gmail.com>
Thu, 5 Mar 2015 19:24:43 +0000 (14:24 -0500)
committerZoltan Varga <vargaz@gmail.com>
Thu, 5 Mar 2015 19:24:50 +0000 (14:24 -0500)
mono/metadata/marshal.c
mono/tests/libtest.c
mono/tests/pinvoke2.cs

index 90563d6bbc19fb5234f67b1c535a919fa1c55e86..6eaa0775a2e5ce394970784100ec4a1243fd04d3 100644 (file)
@@ -6000,6 +6000,31 @@ emit_marshal_array (EmitMarshalContext *m, int argnum, MonoType *t,
                need_free = mono_marshal_need_free (&klass->element_class->byval_arg, 
                                                                                        m->piinfo, spec);
 
+               if ((t->attrs & PARAM_ATTRIBUTE_OUT) && spec && spec->native == MONO_NATIVE_LPARRAY && spec->data.array_data.param_num != -1) {
+                       int param_num = spec->data.array_data.param_num;
+                       MonoType *param_type;
+
+                       param_type = m->sig->params [param_num];
+
+                       if (param_type->byref && param_type->type != MONO_TYPE_I4) {
+                               char *msg = g_strdup ("Not implemented.");
+                               mono_mb_emit_exception_marshal_directive (mb, msg);
+                               break;
+                       }
+
+                       mono_mb_emit_ldarg (mb, argnum);
+
+                       /* Create the managed array */
+                       mono_mb_emit_ldarg (mb, param_num);
+                       if (m->sig->params [param_num]->byref)
+                               // FIXME: Support other types
+                               mono_mb_emit_byte (mb, CEE_LDIND_I4);
+                       mono_mb_emit_byte (mb, CEE_CONV_OVF_I);
+                       mono_mb_emit_op (mb, CEE_NEWARR, klass->element_class);
+                       /* Store into argument */
+                       mono_mb_emit_byte (mb, CEE_STIND_I);
+               }
+
                if (need_convert || need_free) {
                        /* FIXME: Optimize blittable case */
                        MonoClass *eklass;
@@ -6115,6 +6140,8 @@ emit_marshal_array (EmitMarshalContext *m, int argnum, MonoType *t,
                        /* free memory allocated (if any) by MONO_MARSHAL_CONV_ARRAY_LPARRAY */
 
                        mono_mb_emit_ldarg (mb, argnum);
+                       if (t->byref)
+                               mono_mb_emit_byte (mb, CEE_LDIND_REF);
                        mono_mb_emit_ldloc (mb, conv_arg);
                        mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_FREE_LPARRAY));
                }
@@ -6937,7 +6964,9 @@ mono_marshal_emit_native_wrapper (MonoImage *image, MonoMethodBuilder *mb, MonoM
        int type, param_shift = 0;
        static MonoMethodSignature *get_last_error_sig = NULL;
 
+       memset (&m, 0, sizeof (m));
        m.mb = mb;
+       m.sig = sig;
        m.piinfo = piinfo;
 
        /* we copy the signature, so that we can set pinvoke to 0 */
@@ -7799,6 +7828,7 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass,
        csig->hasthis = 0;
        csig->pinvoke = 1;
 
+       memset (&m, 0, sizeof (m));
        m.mb = mb;
        m.sig = sig;
        m.piinfo = NULL;
@@ -7945,6 +7975,7 @@ mono_marshal_get_vtfixup_ftnptr (MonoImage *image, guint32 token, guint16 type)
                csig->hasthis = 0;
                csig->pinvoke = 1;
 
+               memset (&m, 0, sizeof (m));
                m.mb = mb;
                m.sig = sig;
                m.piinfo = NULL;
index 495a44f457a7c3d2a6372a56ba6fa70a3ec7e3f6..4718efb9000f478cd4bd35477c763c40b2e8d0fa 100644 (file)
@@ -411,7 +411,6 @@ mono_test_marshal_unicode_char_array (gunichar2 *s)
        return 0;
 }
 
-
 LIBTEST_API int STDCALL 
 mono_test_empty_pinvoke (int i)
 {
@@ -509,6 +508,22 @@ mono_test_marshal_out_array (int *a1)
        return 0;
 }
 
+LIBTEST_API int STDCALL
+mono_test_marshal_out_byref_array_out_size_param (int **out_arr, int *out_len)
+{
+       int *arr;
+       int i, len;
+
+       len = 4;
+       arr = marshal_alloc (sizeof (gint32) * len);
+       for (i = 0; i < len; ++i)
+               arr [i] = i;
+       *out_arr = arr;
+       *out_len = len;
+
+       return 0;
+}
+
 LIBTEST_API int STDCALL  
 mono_test_marshal_inout_nonblittable_array (gunichar2 *a1)
 {
index edf9a6dad4566e205c8a04c0192bfa77fa4b2563..9a7e83ab859be0a79469cccfc8fc5ed6ecd8efba 100644 (file)
@@ -227,6 +227,9 @@ public class Tests {
        [DllImport ("libtest", EntryPoint="mono_test_marshal_out_array")]
        public static extern int mono_test_marshal_out_array ([Out] [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int [] a1, int n);
 
+       [DllImport ("libtest", EntryPoint="mono_test_marshal_out_byref_array_out_size_param")]
+       public static extern int mono_test_marshal_out_byref_array_out_size_param ([Out] [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] out int [] a1, out int n);
+
        [DllImport ("libtest", EntryPoint="mono_test_marshal_inout_nonblittable_array", CharSet = CharSet.Unicode)]
        public static extern int mono_test_marshal_inout_nonblittable_array ([In, Out] char [] a1);
        
@@ -408,6 +411,19 @@ public class Tests {
                return 0;
        }
 
+       public static int test_0_marshal_out_byref_array_out_size_param () {
+               int [] a1 = null;
+               int len;
+
+               int res = mono_test_marshal_out_byref_array_out_size_param (out a1, out len);
+               if (len != 4)
+                       return 1;
+               for (int i = 0; i < len; i++)
+                       if (a1 [i] != i)
+                               return 2;
+               return 0;
+       }
+
        public static int test_0_marshal_inout_nonblittable_array () {
                char [] a1 = new char [10];
                for (int i = 0; i < 10; i++)