Skip to content

Commit

Permalink
[interp] Fix struct copying during pinvoke transitions (mono/mono#18402)
Browse files Browse the repository at this point in the history
If we are in pinvoke wrapper, we need to use the marshalled native size, not the managed size.

Commit migrated from mono/mono@a13f5cc
  • Loading branch information
BrzVlad authored and akoeplinger committed Jan 13, 2020
1 parent dd840e0 commit be8a81b
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 12 deletions.
12 changes: 10 additions & 2 deletions src/mono/mono/mini/interp/interp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
20 changes: 10 additions & 10 deletions src/mono/mono/tests/libtest.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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)
{
Expand Down
14 changes: 14 additions & 0 deletions src/mono/mono/tests/pinvoke2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<string> 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);

Expand Down Expand Up @@ -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);
}
Expand All @@ -490,6 +494,7 @@ public static int test_0_marshal_struct_gen () {
SimpleStructGen<string> ss = new SimpleStructGen<string> ();
ss.b = true;
ss.d = "TEST";
ss.d2 = "OK";

return mono_test_marshal_struct_gen (ss);
}
Expand Down Expand Up @@ -852,6 +857,15 @@ public static int test_0_return_vtype () {
return 1;
}

public static int test_0_return_vtype_gen () {
SimpleStructGen<string> 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");
Expand Down

0 comments on commit be8a81b

Please sign in to comment.