Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fix Marshal.SizeOf() for structs with explicit layout

	Marshal.SizeOf is now returning the expected values for explicit layout
	in 32 and 64 bits systems.

	Fixes bug #641535.
  • Loading branch information...
commit ed74f971db7a985dbf7df956795c5653a0e32da8 1 parent ad115a8
@gonzalop gonzalop authored
Showing with 65 additions and 5 deletions.
  1. +11 −4 mono/metadata/marshal.c
  2. +54 −1 mono/tests/marshal7.cs
View
15 mono/metadata/marshal.c
@@ -10614,7 +10614,7 @@ MonoMarshalType *
mono_marshal_load_type_info (MonoClass* klass)
{
int j, count = 0;
- guint32 native_size = 0, min_align = 1;
+ guint32 native_size = 0, min_align = 1, packing;
MonoMarshalType *info;
MonoClassField* field;
gpointer iter;
@@ -10671,6 +10671,7 @@ mono_marshal_load_type_info (MonoClass* klass)
info->native_size = parent_size;
}
+ packing = klass->packing_size ? klass->packing_size : 8;
iter = NULL;
j = 0;
while ((field = mono_class_get_fields (klass, &iter))) {
@@ -10709,8 +10710,7 @@ mono_marshal_load_type_info (MonoClass* klass)
case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
size = mono_marshal_type_size (field->type, info->fields [j].mspec,
&align, TRUE, klass->unicode);
- align = klass->packing_size ? MIN (klass->packing_size, align): align;
- min_align = MAX (align, min_align);
+ min_align = packing;
info->fields [j].offset = field->offset - sizeof (MonoObject);
info->native_size = MAX (info->native_size, info->fields [j].offset + size);
break;
@@ -10718,8 +10718,15 @@ mono_marshal_load_type_info (MonoClass* klass)
j++;
}
- if(layout != TYPE_ATTRIBUTE_AUTO_LAYOUT) {
+ if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT) {
info->native_size = MAX (native_size, info->native_size);
+ /*
+ * If the provided Size is equal or larger than the calculated size, and there
+ * was no Pack attribute, we set min_align to 1 to avoid native_size being increased
+ */
+ if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT)
+ if (native_size && native_size == info->native_size && klass->packing_size == 0)
+ min_align = 1;
}
if (info->native_size & (min_align - 1)) {
View
55 mono/tests/marshal7.cs
@@ -51,6 +51,50 @@ public class TestStruct7
object itf;
}
+ // Size should be 12 in both 32 and 64 bits
+ [StructLayout (LayoutKind.Explicit)]
+ struct TestStruct8 {
+ [FieldOffset (0)]
+ public int a;
+ [FieldOffset (4)]
+ public ulong b;
+ }
+
+ // Size should be 12 in both 32 and 64 bits
+ [StructLayout (LayoutKind.Explicit, Size=12)]
+ struct TestStruct9 {
+ [FieldOffset (0)]
+ public int a;
+ [FieldOffset (4)]
+ public ulong b;
+ }
+
+ // Size should be 11 in both 32 and 64 bits
+ [StructLayout (LayoutKind.Explicit)]
+ struct TestStruct10 {
+ [FieldOffset (0)]
+ public int a;
+ [FieldOffset (3)]
+ public ulong b;
+ }
+
+ // Size should be 11 in both 32 and 64 bits
+ [StructLayout (LayoutKind.Explicit, Size=11)]
+ struct TestStruct11 {
+ [FieldOffset (0)]
+ public int a;
+ [FieldOffset (3)]
+ public ulong b;
+ }
+
+ [StructLayout (LayoutKind.Explicit, Pack=1)]
+ struct TestStruct12 {
+ [FieldOffset (0)]
+ public short a;
+ [FieldOffset (2)]
+ public int b;
+ }
+
public unsafe static int Main ()
{
///
@@ -137,7 +181,16 @@ public unsafe static int Main ()
// a VARIANT is
if (Marshal.SizeOf (typeof (TestStruct7)) != 16)
return 13;
-
+ if (Marshal.SizeOf (typeof (TestStruct8)) != 16)
+ return 14;
+ if (Marshal.SizeOf (typeof (TestStruct9)) != 12)
+ return 15;
+ if (Marshal.SizeOf (typeof (TestStruct10)) != 16)
+ return 16;
+ if (Marshal.SizeOf (typeof (TestStruct11)) != 11)
+ return 17;
+ if (Marshal.SizeOf (typeof (TestStruct12)) != 6)
+ return 18;
return 0;
}
}
Please sign in to comment.
Something went wrong with that request. Please try again.