From be8a81b7ed7f87e3cc9d9296bacbb142b3b1d0fd Mon Sep 17 00:00:00 2001 From: Vlad Brezae Date: Mon, 13 Jan 2020 03:05:25 -0800 Subject: [PATCH] [interp] Fix struct copying during pinvoke transitions (mono/mono#18402) If we are in pinvoke wrapper, we need to use the marshalled native size, not the managed size. Commit migrated from https://github.com/mono/mono/commit/a13f5ccbb60d162fe3a8ffdbb9cd61c9c1f8a425 --- src/mono/mono/mini/interp/interp.c | 12 ++++++++++-- src/mono/mono/tests/libtest.c | 20 ++++++++++---------- src/mono/mono/tests/pinvoke2.cs | 14 ++++++++++++++ 3 files changed, 34 insertions(+), 12 deletions(-) diff --git a/src/mono/mono/mini/interp/interp.c b/src/mono/mono/mini/interp/interp.c index 641b67be157e9..c4d3e65ff8ba8 100644 --- a/src/mono/mono/mini/interp/interp.c +++ b/src/mono/mono/mini/interp/interp.c @@ -893,7 +893,11 @@ stackval_from_data (MonoType *type, stackval *result, const void *data, gboolean return; case MONO_TYPE_GENERICINST: { if (mono_type_generic_inst_is_valuetype (type)) { - mono_value_copy_internal (result->data.vt, data, mono_class_from_mono_type_internal (type)); + MonoClass *klass = mono_class_from_mono_type_internal (type); + if (pinvoke) + memcpy (result->data.vt, data, mono_class_native_size (klass, NULL)); + else + mono_value_copy_internal (result->data.vt, data, klass); return; } stackval_from_data (m_class_get_byval_arg (type->data.generic_class->container_class), result, data, pinvoke); @@ -996,7 +1000,11 @@ stackval_to_data (MonoType *type, stackval *val, void *data, gboolean pinvoke) MonoClass *container_class = type->data.generic_class->container_class; if (m_class_is_valuetype (container_class) && !m_class_is_enumtype (container_class)) { - mono_value_copy_internal (data, val->data.vt, mono_class_from_mono_type_internal (type)); + MonoClass *klass = mono_class_from_mono_type_internal (type); + if (pinvoke) + memcpy (data, val->data.vt, mono_class_native_size (klass, NULL)); + else + mono_value_copy_internal (data, val->data.vt, klass); return; } stackval_to_data (m_class_get_byval_arg (type->data.generic_class->container_class), val, data, pinvoke); diff --git a/src/mono/mono/tests/libtest.c b/src/mono/mono/tests/libtest.c index 2508b1ddaf2d7..bd146f831890a 100644 --- a/src/mono/mono/tests/libtest.c +++ b/src/mono/mono/tests/libtest.c @@ -699,16 +699,6 @@ mono_test_marshal_delegate_struct (DelegateStruct ds) return res; } -LIBTEST_API int STDCALL -mono_test_marshal_struct (simplestruct ss) -{ - if (ss.a == 0 && ss.b == 1 && ss.c == 0 && - !strcmp (ss.d, "TEST")) - return 0; - - return 1; -} - LIBTEST_API int STDCALL mono_test_marshal_byref_struct (simplestruct *ss, int a, int b, int c, char *d) { @@ -953,6 +943,16 @@ is_utf16_equals (gunichar2 *s1, const char *s2) return res == 0; } +LIBTEST_API int STDCALL +mono_test_marshal_struct (simplestruct ss) +{ + if (ss.a == 0 && ss.b == 1 && ss.c == 0 && + !strcmp (ss.d, "TEST") && is_utf16_equals (ss.d2, "OK")) + return 0; + + return 1; +} + LIBTEST_API int STDCALL mono_test_marshal_delegate2 (SimpleDelegate2 delegate) { diff --git a/src/mono/mono/tests/pinvoke2.cs b/src/mono/mono/tests/pinvoke2.cs index 1528dd57c74d1..07ae1dce2957c 100644 --- a/src/mono/mono/tests/pinvoke2.cs +++ b/src/mono/mono/tests/pinvoke2.cs @@ -314,6 +314,9 @@ public struct BStrStruct [DllImport ("libtest", EntryPoint="mono_test_return_vtype")] public static extern SimpleStruct mono_test_return_vtype (IntPtr i); + [DllImport ("libtest", EntryPoint="mono_test_return_vtype")] + public static extern SimpleStructGen mono_test_return_vtype_gen (IntPtr i); + [DllImport ("libtest", EntryPoint="mono_test_marshal_stringbuilder")] public static extern void mono_test_marshal_stringbuilder (StringBuilder sb, int len); @@ -482,6 +485,7 @@ public static int test_0_marshal_struct () { SimpleStruct ss = new SimpleStruct (); ss.b = true; ss.d = "TEST"; + ss.d2 = "OK"; return mono_test_marshal_struct (ss); } @@ -490,6 +494,7 @@ public static int test_0_marshal_struct_gen () { SimpleStructGen ss = new SimpleStructGen (); ss.b = true; ss.d = "TEST"; + ss.d2 = "OK"; return mono_test_marshal_struct_gen (ss); } @@ -852,6 +857,15 @@ public static int test_0_return_vtype () { return 1; } + public static int test_0_return_vtype_gen () { + SimpleStructGen ss = mono_test_return_vtype_gen (new IntPtr (5)); + + if (!ss.a && ss.b && !ss.c && ss.d == "TEST" && ss.d2 == "TEST2") + return 0; + + return 1; + } + public static int test_0_marshal_stringbuilder () { StringBuilder sb = new StringBuilder(255); sb.Append ("ABCD");