Don't consider types with empty base classes blittable. They have a different managed...
authorJeremy Koritzinsky <jekoritz@microsoft.com>
Thu, 7 Jan 2021 02:39:01 +0000 (18:39 -0800)
committerGitHub <noreply@github.com>
Thu, 7 Jan 2021 02:39:01 +0000 (18:39 -0800)
* 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
src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/SizeOfTests.cs

index e5f9345..bdef0e4 100644 (file)
@@ -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*));
index 5d866c7..6a009a0 100644 (file)
@@ -59,6 +59,12 @@ namespace System.Runtime.InteropServices.Tests
             Assert.Equal(8, Marshal.SizeOf<TestStructWithVector64>());
         }
 
+        [Fact]
+        public void SizeOf_TypeWithEmptyBase_ReturnsExpected()
+        {
+            Assert.Equal(4, Marshal.SizeOf<DerivedClass>());
+        }
+
         public static IEnumerable<object[]> 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<double> v;
         }
+
+        [StructLayout(LayoutKind.Sequential)]
+        public class EmptyClass
+        {
+        }
+
+        [StructLayout(LayoutKind.Sequential)]
+        public class DerivedClass : EmptyClass
+        {
+            public int i;
+        }
     }
 }