Skip to content

Commit

Permalink
Fix Marshal.SizeOf() for structs with explicit layout
Browse files Browse the repository at this point in the history
	Marshal.SizeOf is now returning the expected values for explicit layout
	in 32 and 64 bits systems.

	Fixes bug #641535.
  • Loading branch information
gonzalop committed Oct 8, 2010
1 parent ad115a8 commit ed74f97
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 5 deletions.
15 changes: 11 additions & 4 deletions mono/metadata/marshal.c
Expand Up @@ -10614,7 +10614,7 @@ MonoMarshalType *
mono_marshal_load_type_info (MonoClass* klass) mono_marshal_load_type_info (MonoClass* klass)
{ {
int j, count = 0; int j, count = 0;
guint32 native_size = 0, min_align = 1; guint32 native_size = 0, min_align = 1, packing;
MonoMarshalType *info; MonoMarshalType *info;
MonoClassField* field; MonoClassField* field;
gpointer iter; gpointer iter;
Expand Down Expand Up @@ -10671,6 +10671,7 @@ mono_marshal_load_type_info (MonoClass* klass)
info->native_size = parent_size; info->native_size = parent_size;
} }


packing = klass->packing_size ? klass->packing_size : 8;
iter = NULL; iter = NULL;
j = 0; j = 0;
while ((field = mono_class_get_fields (klass, &iter))) { while ((field = mono_class_get_fields (klass, &iter))) {
Expand Down Expand Up @@ -10709,17 +10710,23 @@ mono_marshal_load_type_info (MonoClass* klass)
case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
size = mono_marshal_type_size (field->type, info->fields [j].mspec, size = mono_marshal_type_size (field->type, info->fields [j].mspec,
&align, TRUE, klass->unicode); &align, TRUE, klass->unicode);
align = klass->packing_size ? MIN (klass->packing_size, align): align; min_align = packing;
min_align = MAX (align, min_align);
info->fields [j].offset = field->offset - sizeof (MonoObject); info->fields [j].offset = field->offset - sizeof (MonoObject);
info->native_size = MAX (info->native_size, info->fields [j].offset + size); info->native_size = MAX (info->native_size, info->fields [j].offset + size);
break; break;
} }
j++; j++;
} }


if(layout != TYPE_ATTRIBUTE_AUTO_LAYOUT) { if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT) {
info->native_size = MAX (native_size, info->native_size); 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)) { if (info->native_size & (min_align - 1)) {
Expand Down
55 changes: 54 additions & 1 deletion mono/tests/marshal7.cs
Expand Up @@ -51,6 +51,50 @@ public class TestStruct7
object itf; 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 () public unsafe static int Main ()
{ {
/// ///
Expand Down Expand Up @@ -137,7 +181,16 @@ public unsafe static int Main ()
// a VARIANT is // a VARIANT is
if (Marshal.SizeOf (typeof (TestStruct7)) != 16) if (Marshal.SizeOf (typeof (TestStruct7)) != 16)
return 13; 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; return 0;
} }
} }
Expand Down

0 comments on commit ed74f97

Please sign in to comment.