From 15be6302e64b2a5df7d169bff7a2e876e1e4d400 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Wed, 6 Jan 2021 18:39:01 -0800 Subject: [PATCH] Don't consider types with empty base classes blittable. They have a different managed and native size. (#46653) * Don't consider types with empty base classes blittable. They have a different managed and native size. * Add test. * Update src/coreclr/vm/classlayoutinfo.cpp --- src/coreclr/vm/classlayoutinfo.cpp | 8 ++++++-- .../Runtime/InteropServices/Marshal/SizeOfTests.cs | 17 +++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/coreclr/vm/classlayoutinfo.cpp b/src/coreclr/vm/classlayoutinfo.cpp index e5f9345..bdef0e4 100644 --- a/src/coreclr/vm/classlayoutinfo.cpp +++ b/src/coreclr/vm/classlayoutinfo.cpp @@ -653,8 +653,12 @@ VOID EEClassLayoutInfo::CollectLayoutFieldMetadataThrowing( DEBUGARG(szName) ); - // Type is blittable only if parent is also blittable - isBlittable = isBlittable && (fHasNonTrivialParent ? pParentMT->IsBlittable() : TRUE); + // Type is blittable only if parent is also blittable and is not empty. + if (isBlittable && fHasNonTrivialParent) + { + isBlittable = pParentMT->IsBlittable() // Check parent + && (!pParentLayoutInfo || !pParentLayoutInfo->IsZeroSized()); // Ensure non-zero size + } pEEClassLayoutInfoOut->SetIsBlittable(isBlittable); S_UINT32 cbSortArraySize = S_UINT32(cTotalFields) * S_UINT32(sizeof(LayoutRawFieldInfo*)); diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/SizeOfTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/SizeOfTests.cs index 5d866c7..6a009a0 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/SizeOfTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/SizeOfTests.cs @@ -59,6 +59,12 @@ namespace System.Runtime.InteropServices.Tests Assert.Equal(8, Marshal.SizeOf()); } + [Fact] + public void SizeOf_TypeWithEmptyBase_ReturnsExpected() + { + Assert.Equal(4, Marshal.SizeOf()); + } + public static IEnumerable SizeOf_InvalidType_TestData() { yield return new object[] { typeof(int).MakeByRefType(), null }; @@ -136,5 +142,16 @@ namespace System.Runtime.InteropServices.Tests { public System.Runtime.Intrinsics.Vector64 v; } + + [StructLayout(LayoutKind.Sequential)] + public class EmptyClass + { + } + + [StructLayout(LayoutKind.Sequential)] + public class DerivedClass : EmptyClass + { + public int i; + } } } -- 2.7.4