Uh oh!
There was an error while loading. Please reload this page.
Fix NullReferenceException in DestroyStructure for blittable types - #126795
Conversation
Tagging subscribers to this area: @dotnet/area-infrastructure-libraries |
…littable types in StructureMarshaler and LayoutClassMarshaler For blittable types, FreeCore is a no-op (uses the C# body since TryGenerateStructMarshallingMethod returns false for blittable types). Calling NativeMemory.Clear on a potentially invalid pointer (like (IntPtr)1 used in tests) causes a NullReferenceException/fault. Fix by: 1. Adding s_isBlittable static field to StructureMarshaler<T> (initialized via Marshal.HasLayout) 2. Adding IsBlittable property to LayoutClassMarshaler<T>.Methods (using existing s_nativeSizeForBlittableTypes) 3. Skipping FreeCore and NativeMemory.Clear in both Free() methods for blittable types This restores the original behavior where DestroyStructure is a no-op for blittable types. Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/f610b358-8378-4bba-b4dd-98615601bdeb Co-authored-by: jkoritzinsky <1571408+jkoritzinsky@users.noreply.github.com>
…ds.IsBlittable Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/f610b358-8378-4bba-b4dd-98615601bdeb Co-authored-by: jkoritzinsky <1571408+jkoritzinsky@users.noreply.github.com>
am11
commented
Apr 11, 2026
Failure seems related https://helix.dot.net/api/2019-06-17/jobs/ac25ae7c-952e-4650-900f-5f3fcb70ec27/workitems/Interop/consol |
Uh oh!
There was an error while loading. Please reload this page.
…ception try-catch pattern Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/f3d7123a-231f-4ec5-9460-294f83aeb412 Co-authored-by: jkoritzinsky <1571408+jkoritzinsky@users.noreply.github.com>
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Pull request overview
Fixes a crash in Marshal.DestroyStructure for blittable layout types by avoiding NativeMemory.Clear on potentially invalid pointers (e.g., (IntPtr)1), and preserves the existing “unwrap TypeInitializationException” behavior for blittable detection in the layout-class marshaler.
Changes:
- Skip
FreeCore/NativeMemory.ClearinStructureMarshaler<T>.FreewhenTis blittable (computed once viaMarshal.HasLayout). - Add
Methods.IsBlittable+GetIsBlittable()wrapper inLayoutClassMarshaler<T>and makeFreea no-op for blittable layout classes. - Keep
NativeMemory.Clearfor non-blittable types to prevent double-free after nested cleanup.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
danmoseley
commented
Apr 12, 2026
is there a build analysis pattern for this? would be good for various pr's hitting it |
am11
commented
Apr 12, 2026
Not sure why automerge failed here; BA is green? |
danmoseley
commented
Apr 12, 2026
Conversations need to be resolved i think |
jkoritzinsky
commented
Apr 12, 2026
Yes the closed issue had the BA template. |
Description
BoxedLayoutTypeMarshaler<T>(introduced in #126621) routesDestroyStructurefor blittable value types throughStructureMarshaler<T>.Free, which unconditionally calledNativeMemory.Clear(ptr, size)even whenFreeCorewas a no-op. Passing an invalid pointer like(IntPtr)1— the longstanding test pattern for "blittable types should be a no-op" — faults at address 1, manifesting as aNullReferenceExceptionon Android.Changes
StructureMarshaler<T>: Added as_isBlittablestatic field (initialized once viaMarshal.HasLayout).Free()now skips bothFreeCoreandNativeMemory.Clearfor blittable types. For non-blittable types (array marshaling path viaNonBlittableStructureArrayFree), the JIT generates aFreeCoreIL stub that frees native sub-structures;NativeMemory.Clearstill follows to prevent double-free.LayoutClassMarshaler<T>.Methods: AddedIsBlittableproperty using the existings_nativeSizeForBlittableTypesfield (non-zero ⟺ blittable). Access toIsBlittableis wrapped in aGetIsBlittable()method that follows the same[MethodImpl(MethodImplOptions.NoInlining)]+try/catch (TypeInitializationException)pattern used by all otherMethodsaccessors, ensuringTypeLoadExceptionis surfaced instead ofTypeInitializationExceptionon recursive native layout failures.Free()is now a no-op for blittable reference types — same fix, same reasoning.Testing
Existing
DestroyStructure_Blittable_Successtest covers the regression. FullSystem.Runtime.InteropServices.Testssuite: 2549 passed, 0 failed.