Skip to content

Fix VerificationException when marshalling non-blittable struct arrays in trimmed apps#129525

Closed
kotlarmilos wants to merge 1 commit into
dotnet:mainfrom
kotlarmilos:fix-128027-structuremarshaler-trimming
Closed

Fix VerificationException when marshalling non-blittable struct arrays in trimmed apps#129525
kotlarmilos wants to merge 1 commit into
dotnet:mainfrom
kotlarmilos:fix-128027-structuremarshaler-trimming

Conversation

@kotlarmilos

@kotlarmilos kotlarmilos commented Jun 17, 2026

Copy link
Copy Markdown
Member

Description

Right now, any trimmed app that marshals an array of a non-blittable struct crashes with a VerificationException. The biggest impact is that net11.0-android Release build fails to start, since Android's startup marshals a JniNativeMethodRegistration[]. The cause is that the runtime generates the array-marshalling code at runtime, referencing helper types like StructureMarshaler<T> by name from native code. The trimmer can't see those references, so it strips the interface implementations those helpers rely on, and the constraint check blows up at runtime.

Fixes #128027

Copilot AI review requested due to automatic review settings June 17, 2026 14:39
@dotnet-policy-service dotnet-policy-service Bot added the linkable-framework Issues associated with delivering a linker friendly framework label Jun 17, 2026
@kotlarmilos kotlarmilos force-pushed the fix-128027-structuremarshaler-trimming branch from 78e1d90 to 940c50b Compare June 17, 2026 14:40
@kotlarmilos kotlarmilos force-pushed the fix-128027-structuremarshaler-trimming branch 2 times, most recently from 60793fd to 32b4ba7 Compare June 17, 2026 14:47
…8027)

Trimmed apps throw System.Security.VerificationException whenever they
marshal an array of a non-blittable struct (e.g. via
[MarshalAs(UnmanagedType.LPArray/ByValArray)] or Marshal.StructureToPtr).
This breaks every net11.0-android Release build at startup, because
Java.Interop's JNIEnvInit.Initialize marshals a JniNativeMethodRegistration[]
LPArray before any user code runs; iOS/tvOS Release builds are affected too.

The runtime's IL-stub generator references the array (element) marshalers
by name from native code (CLASS__*_MARSHALER in src/coreclr/vm/corelib.h)
and passes them as the TMarshaler type argument to
ConvertArraySpaceToNative<T, TMarshaler> / FreeArrayContents<T, TMarshaler>,
whose generic constraint requires the IArrayMarshaler<T, TMarshaler>
static-abstract implementation. The trimmer cannot see these uses (the
P/Invoke marshalling stub is generated at runtime by the VM), so it strips
the static-virtual interface implementations and the constraint check fails
at runtime.

Preserve the always-present (non-COM-interop) StubHelpers marshalers in
ILLink.Descriptors.Shared.xml. These entries were originally added by
dotnet#128020 and removed by dotnet#128272 on the assumption the illink-side fix for
dotnet#128120 was sufficient; it is not for the runtime-generated P/Invoke stub
path, which has no managed reference for the trimmer to follow.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@kotlarmilos kotlarmilos force-pushed the fix-128027-structuremarshaler-trimming branch from 32b4ba7 to f4311a4 Compare June 17, 2026 14:49

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates CoreLib’s ILLink shared descriptor roots to keep specific System.StubHelpers array-marshaler types that are referenced by name from native IL-stub generation, and adds a trimming regression test that exercises marshalling an array of a non-blittable struct in a fully-trimmed app scenario.

Changes:

  • Root additional System.StubHelpers array marshalers in ILLink.Descriptors.Shared.xml to prevent trimming from removing required static-interface implementations.
  • Add a new trimming regression console-app test source that marshals a non-blittable struct array via Marshal.StructureToPtr.
  • Exclude Microsoft.Extensions.DependencyInjection.ExternalContainers tests for certain Apple simulator/MacCatalyst CoreCLR lanes.
Show a summary per file
File Description
src/libraries/tests.proj Adds a platform-specific test project exclusion for Apple simulator/MacCatalyst CoreCLR runs.
src/libraries/System.Runtime.InteropServices/tests/TrimmingTests/System.Runtime.InteropServices.TrimmingTests.proj Registers the new trimming regression console-app test source file.
src/libraries/System.Runtime.InteropServices/tests/TrimmingTests/MarshalNonBlittableStructArrayTrimmed.cs New trimming regression repro that marshals a non-blittable struct array and expects success (exit code 100).
src/coreclr/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.Shared.xml Adds descriptor roots for System.StubHelpers marshalers used by runtime-generated array marshalling stubs.

Copilot's findings

  • Files reviewed: 1/1 changed files
  • Comments generated: 0

@kotlarmilos

Copy link
Copy Markdown
Member Author

The issue is already fixed on main by #128272. This descriptor update is not needed, I was using stale artifacts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-System.Runtime.InteropServices linkable-framework Issues associated with delivering a linker friendly framework

Projects

None yet

Development

Successfully merging this pull request may close these issues.

VerificationException from StructureMarshaler<T> on any trimmed app marshalling a non-blittable struct array (regression in P5)

2 participants