Skip to content

Calling a Vararg P/Invoke from another assembly fails to call underlying native function #87188

Open
@jkoritzinsky

Description

@jkoritzinsky

Description

When calling a vararg P/Invoke defined in another assembly, the runtime tries to look up the metadata from the wrong module. This can cause a variety of issues, from throwing a BadImageFormatException to emitting an incorrect stub signature.

Reproduction Steps

Define the following P/Invoke in assembly A:

[DllImport("msvcrt.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static unsafe extern int _scprintf(string format, __arglist);

Call it from another assembly (Assembly B):

_scprintf("%d\n", __arglist(42));

Expected behavior

"42" is printed out to the console.

Actual behavior

BadImageFormatException if the method token for _scprintf is higher than the highest valid method token in assembly B.

Stack corruption if the method token for _scprintf in Assembly A corresponds to a method in Assembly B without the preservesig metadata bit set.

Regression?

Based on code inspection, this issue has likely been present since .NET Framework.

Known Workarounds

Move the call to the P/Invoke to the same assembly as the caller (or vice versa).

Configuration

.NET 7.0.3 Windows x86

Other information

The failure is due to this line using m_pModule instead of m_pMetadataModule:

IMDInternalImport* pInternalImport = pSigDesc->m_pModule->GetMDImport();

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status

    No status

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions