You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[wasm][R2R] GC hole: custom attribute instances get a dangling string field under GCStress #134777
On browser-wasm CoreCLR with R2R code, custom attribute objects built by Assembly.GetCustomAttributes can end up with a dangling reference field when a GC happens during their construction. Under DOTNET_GCStress=0x1, a later GC or validation of the attribute's culture string hits SanityCheck().
No exception handling is involved, so this is separate from the aborted-funclet hole fixed in #134769.
It shows up in the Methodical_d1 runtime tests as an intermittent RawGetMethodTable() assert in SetMarked during JitTest_throw_SEH_cs.Test.TestEntryPoint. There, Exception.ToString() loads a resource string for the first time in the process. That goes through ResourceManager, which reads the NeutralResourcesLanguageAttribute via RuntimeCustomAttribute.GetCustomAttributes(QCustomAttributeList, int, RuntimeType). The failing root is attributes._item, a live ListBuilder<object> slot in that frame. The attribute object itself validates, and the assert fires while marking an object reachable from it.
Reproduction Steps
usingSystem;usingSystem.Reflection;usingSystem.Resources;staticclassProgram{staticintMain(){Assembly[]asms={typeof(object).Assembly,typeof(System.Reflection.Metadata.MetadataReader).Assembly,typeof(Console).Assembly};intbad=0,n=0;for(inti=0;i<60;i++){foreach(Assemblyainasms){object[]attrs=a.GetCustomAttributes(typeof(NeutralResourcesLanguageAttribute),false);foreach(NeutralResourcesLanguageAttributeattrinattrs){n++;if(attr.CultureNameis not {Length:>0})bad++;}}}Console.WriteLine($"attrs={n} bad={bad}");returnbad==0&&n>0?100:1;}}
Build the program for net11.0 and R2R-compile it with crossgen2 using --targetarch:wasm --targetos:browser -f wasm -O --codegenopt:JitWasmNyiToR2RUnsupported=1.
Run it with a checked browser-wasm corerun under node, using the Core_Root from a runtime-tests Helix payload, with DOTNET_TieredCompilation=0 and DOTNET_GCStress=0x1.
Expected behavior
Prints attrs=180 bad=0 and exits with 100, as it does without GC stress.
It fails identically with and without the fix in #134769.
Regression?
Unknown. On CI it was hidden, because the test that reaches it (throw_SEH) crashed earlier on the EH hole fixed in #134769.
Known Workarounds
None.
Configuration
browser-wasm CoreCLR, Checked runtime (main as of 2026-09-28), CoreLib and Core_Root from the Methodical_d1 Helix payload of build 1613981.
Test assembly R2R-compiled to Wasm. Main itself runs in the interpreter (IR_ offsets).
node 26.4.0, macOS arm64 host.
Other information
In Methodical_d1, the failure is intermittent. It depends on the first-time resource load happening at a bad GC point, and randomized string hashing probably varies where that happens. The standalone repro above is deterministic.
Not yet root-caused. Likely suspects are where attribute constructor arguments are created and passed: the string argument parsed from the CA blob as it goes through reflection invoke and the R2R/interpreter thunks.
Description
On browser-wasm CoreCLR with R2R code, custom attribute objects built by
Assembly.GetCustomAttributescan end up with a dangling reference field when a GC happens during their construction. UnderDOTNET_GCStress=0x1, a later GC or validation of the attribute's culture string hitsSanityCheck().No exception handling is involved, so this is separate from the aborted-funclet hole fixed in #134769.
It shows up in the
Methodical_d1runtime tests as an intermittentRawGetMethodTable()assert inSetMarkedduringJitTest_throw_SEH_cs.Test.TestEntryPoint. There,Exception.ToString()loads a resource string for the first time in the process. That goes throughResourceManager, which reads theNeutralResourcesLanguageAttributeviaRuntimeCustomAttribute.GetCustomAttributes(QCustomAttributeList, int, RuntimeType). The failing root isattributes._item, a liveListBuilder<object>slot in that frame. The attribute object itself validates, and the assert fires while marking an object reachable from it.Reproduction Steps
net11.0and R2R-compile it with crossgen2 using--targetarch:wasm --targetos:browser -f wasm -O --codegenopt:JitWasmNyiToR2RUnsupported=1.corerununder node, using the Core_Root from a runtime-tests Helix payload, withDOTNET_TieredCompilation=0andDOTNET_GCStress=0x1.Expected behavior
Prints
attrs=180 bad=0and exits with 100, as it does without GC stress.Actual behavior
Fails every time (4/4 runs) with:
It fails identically with and without the fix in #134769.
Regression?
Unknown. On CI it was hidden, because the test that reaches it (
throw_SEH) crashed earlier on the EH hole fixed in #134769.Known Workarounds
None.
Configuration
mainas of 2026-09-28), CoreLib and Core_Root from theMethodical_d1Helix payload of build 1613981.Mainitself runs in the interpreter (IR_offsets).Other information
In
Methodical_d1, the failure is intermittent. It depends on the first-time resource load happening at a bad GC point, and randomized string hashing probably varies where that happens. The standalone repro above is deterministic.Not yet root-caused. Likely suspects are where attribute constructor arguments are created and passed: the string argument parsed from the CA blob as it goes through reflection invoke and the R2R/interpreter thunks.
Note
This issue was drafted with GitHub Copilot.