Skip to content

Commit

Permalink
The DestroyStructure API passes null to the IL marshaller for (#61985)
Browse files Browse the repository at this point in the history
managed valuetypes. This is an issue with field marshallers of
  nested non-blittable types.
  • Loading branch information
AaronRobinsonMSFT authored Nov 24, 2021
1 parent 5a3070c commit 7cfcbb0
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 0 deletions.
8 changes: 8 additions & 0 deletions src/coreclr/vm/ilmarshalers.h
Original file line number Diff line number Diff line change
Expand Up @@ -988,11 +988,19 @@ class ILMarshaler

m_nativeHome.InitHome(ILStubMarshalHome::HomeType_ILByrefLocal, pcsSetup->NewLocal(nativeFieldTypeByRef), &nativeType, /* unalignedIndirectStore */ true);

// During the cleanup pass, the managed typed is explicitly passed as null - see DestroyStructure(). This works
// except if the type has nested non-blittable fields. Not checking for null will compute invalid offsets that
// can cause an access violation during the field clean-up.
ILCodeLabel *pSkipComputeOffsetLabel = pcsSetup->NewCodeLabel();

pcsSetup->EmitNOP("// field setup {");
pcsSetup->EmitNOP("// managed field setup {");
pcsSetup->EmitLDARG(StructMarshalStubs::MANAGED_STRUCT_ARGIDX);
pcsSetup->EmitDUP();
pcsSetup->EmitBRFALSE(pSkipComputeOffsetLabel);
pcsSetup->EmitLDC(managedOffset);
pcsSetup->EmitADD();
pcsSetup->EmitLabel(pSkipComputeOffsetLabel);
EmitStoreManagedHomeAddr(pcsSetup);
pcsSetup->EmitNOP("// } managed field setup");
pcsSetup->EmitNOP("// native field setup {");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,30 @@ public unsafe void StructureToPtr_OpaqueStruct_In_NonBlittableStructure_Success(
Assert.Equal(*opaqueData, *marshaledOpaqueData);
}

[Fact]
public void StructureToPtr_Flat_And_Nested_NonBlittableStructure_Success()
{
MarshalAndDestroy(new NonBlittableStruct_Flat
{
del = null,
b = 0x55,
});

MarshalAndDestroy(new NonBlittableStruct_Nested
{
s = { del = null },
b = 0x55,
});

static unsafe void MarshalAndDestroy<T>(T value) where T : struct
{
int sizeof_T = Marshal.SizeOf<T>();
void* ptr = stackalloc byte[sizeof_T];
Marshal.StructureToPtr(value, (IntPtr)ptr, false);
Marshal.DestroyStructure<T>((IntPtr)ptr);
}
}

public struct StructWithIntField
{
public int value;
Expand Down Expand Up @@ -318,5 +342,22 @@ public struct NonBlittableWithOpaque
public OpaqueStruct opaque;
public string str;
}

public struct NonBlittableStruct_Flat
{
public Delegate del;
public byte b;
}

public struct NonBlittableStruct_Nested
{
public struct InnerStruct
{
public Delegate del;
}

public InnerStruct s;
public byte b;
}
}
}

0 comments on commit 7cfcbb0

Please sign in to comment.