Skip to content

StructureMarshaler doesn't guard from non-struct type arguments #129649

Description

@hez2010

In StructureMarshaler<T> it only requires T to be notnull, which allows arbitrary generic instantiations including invalid ones like StructureMarshaler<object>:

internal sealed unsafe class StructureMarshaler<T> : IArrayElementMarshaler<T, StructureMarshaler<T>> where T : notnull

This can trigger a VM assertion later in dllimport.cpp:

_ASSERTE(pStructMT->IsValueType());

Repro:

using System.Reflection;
using System.Runtime.CompilerServices;

class Program
{
    static void Main()
    {
        var t = Type.GetType("System.StubHelpers.StructureMarshaler`1")!.MakeGenericType(typeof(object));
        RuntimeHelpers.RunClassConstructor(t.TypeHandle);
        var m = t.GetMethod("System.StubHelpers.IArrayElementMarshaler<T,System.StubHelpers.StructureMarshaler<T>>.ConvertToManaged", BindingFlags.NonPublic | BindingFlags.Static)!;
        RuntimeHelpers.PrepareMethod(m.MethodHandle);
    }
}

Result:

Assert failure(PID 21880 [0x00005578], Thread: 62180 [0xf2e4]): pStructMT->IsValueType()

CORECLR! StructMarshalStubs::TryGenerateStructMarshallingMethod + 0x69D (0x00007ffc`84c27c2d)
CORECLR! CEEInfo::getMethodInfoWorker + 0x4F0 (0x00007ffc`849638d0)
CORECLR! CEEInfo::getMethodInfo + 0x35B (0x00007ffc`849631ab)
CLRJIT! `Compiler::impCheckCanInline'::`2'::<lambda_1>::operator() + 0x228 (0x00007ffc`8e0b23a8)
CLRJIT! `Compiler::impCheckCanInline'::`2'::<lambda_1>::<lambda_invoker_cdecl> + 0x16 (0x00007ffc`8e0b1976)
CORECLR! CEEInfo::runWithErrorTrap + 0x2A0 (0x00007ffc`8497bef0)
CLRJIT! Compiler::eeRunWithErrorTrapImp + 0x64 (0x00007ffc`8df15744)
CLRJIT! Compiler::eeRunWithErrorTrap<`Compiler::impCheckCanInline'::`2'::Param> + 0x28 (0x00007ffc`8e0b1d88)
CLRJIT! Compiler::impCheckCanInline + 0x110 (0x00007ffc`8e0b6ef0)
CLRJIT! Compiler::impMarkInlineCandidateHelper + 0x69F (0x00007ffc`8e0c887f)
    File: D:\runtime\src\coreclr\vm\dllimport.cpp:4113
    Image: D:\runtime\artifacts\obj\coreclr\windows.x64.Debug\hosts\corerun\corerun.exe

This was found in jit-dasm-pmi as it will try instantiating a generic type with object and call RuntimeHelpers.PrepareMethod against it.

I think we need either constraint T in StructureMarshaler<T> with struct or make TryGenerateStructMarshallingMethod more resilient.

cc: @MihaZupan

Metadata

Metadata

Assignees

Type

No type

Projects

Status
No status

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions