Fix vararg P/Invoke cross-assembly metadata lookup using wrong module#126106
Open
Fix vararg P/Invoke cross-assembly metadata lookup using wrong module#126106
Conversation
…Module Co-authored-by: jkoritzinsky <1571408+jkoritzinsky@users.noreply.github.com> Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/4b003785-29cc-445b-9d52-64fa68ba9af2
Copilot
AI
changed the title
[WIP] Fix vararg P/Invoke call issues across assemblies
Fix vararg P/Invoke cross-assembly metadata lookup using wrong module
Mar 25, 2026
jkoritzinsky
approved these changes
Mar 25, 2026
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes CoreCLR vararg P/Invoke stub generation for cross-assembly calls by ensuring interop behavior flags (e.g., PreserveSig) are read from the defining module’s metadata, and adds a regression test that calls a vararg [DllImport] declared in a referenced library assembly.
Changes:
- CoreCLR: Use
m_pMetadataModule(defining module) instead ofm_pModule(caller module) when readingMethodImplPropsduring P/Invoke stub creation. - Tests: Add a new cross-assembly varargs scenario via a support library (
VarArgsPInvokeLib) plus a calling test (CrossAssemblyVarargsTest). - Build/test wiring: Reference the new support project from
Interop.csprojand exclude its.csfrom merged wrapper compilation.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/coreclr/vm/dllimport.cpp | Fix metadata importer selection for cross-assembly vararg P/Invoke stub flag lookup. |
| src/tests/Interop/PInvoke/Varargs/CrossAssembly/CrossAssemblyVarargsTest.cs | New regression test that calls vararg P/Invoke across assemblies and validates output. |
| src/tests/Interop/PInvoke/Varargs/CrossAssembly/VarArgsPInvokeLib/VarArgsPInvokeLib.cs | New library that defines the vararg [DllImport] used by the regression test. |
| src/tests/Interop/PInvoke/Varargs/CrossAssembly/VarArgsPInvokeLib/VarArgsPInvokeLib.csproj | New support library project; currently references native CMake project. |
| src/tests/Interop/Interop.csproj | Adds support project reference and excludes library source from merged compilation. |
src/tests/Interop/PInvoke/Varargs/CrossAssembly/VarArgsPInvokeLib/VarArgsPInvokeLib.csproj
Outdated
Show resolved
Hide resolved
Co-authored-by: jkoritzinsky <1571408+jkoritzinsky@users.noreply.github.com> Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/44072add-6b71-4139-b896-eb1f86a283c9
This was referenced Mar 25, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
When a vararg P/Invoke defined in assembly A is called from assembly B, stub creation looks up method implementation flags (e.g.
PreserveSig) using the wrong module's metadata importer — the caller's module rather than the defining module.Root Cause
CreatePInvokeStubAccessMetadatausedpSigDesc->m_pModuleto obtain theIMDInternalImport, but for cross-assembly vararg callsm_pModuleis the caller's module (holds the call-site vararg signature), whilem_tkMethodDefis a token from the defining assembly. The distinction is explicitly documented indllimport.h:Results in either a
BadImageFormatException(token out of range in caller's module) or silent stack corruption (PreserveSigflag incorrectly read from a different method in the caller's module).Fix
src/coreclr/vm/dllimport.cpp— one-line change inCreatePInvokeStubAccessMetadata:Test
src/tests/Interop/PInvoke/Varargs/CrossAssembly/— new cross-assembly test following theMultipleAssembliesWithSamePInvokepattern:VarArgsPInvokeLib— separate library assembly that declares the vararg[DllImport]CrossAssemblyVarargsTest— calls through the lib from the main test assembly, validating correct outputThe
VarArgsPInvokeLibsupport project omits anyCMakeProjectReference— the Varargs native assets are already referenced as Windows-only from the parentInterop.csproj(viaWindowsOnlyCMakeProjectReference), so no additional reference is needed in the library project.Customer Impact
Vararg P/Invoke calls made from a different assembly than the one declaring the import either throw
BadImageFormatExceptionor silently corrupt the stack depending on token layout. Workaround is to co-locate caller and P/Invoke declaration in the same assembly.Regression
No — code inspection suggests this has been present since .NET Framework.
Testing
New
CrossAssemblyVarargsTestexercises the exact failing scenario (vararg P/Invoke defined in a library assembly, called from a separate test assembly). Guarded byIsVarArgSupportedconsistent with existing varargs tests.Risk
Low. Single-line fix confined to the cross-assembly vararg path; the
m_pMetadataModulefield was already being used correctly for theIsRuntimeMarshallingEnabledcheck in the same area. Non-vararg P/Invokes are unaffected (m_pModule == m_pMetadataModulein that case).Original prompt
⚡ Quickly spin up Copilot coding agent tasks from anywhere on your macOS or Windows machine with Raycast.