Repository navigation
CMiniMdRW::PutString stuck in infinite loop #119958
Description
Description
I just ran into a situation where our application (ReSharper backend) got stuck in an infinite loop.
The managed code called System.Reflection.Emit.TypeBuilder.DefineField, which then got stuck with the following callstack:
coreclr!CChainedHash<STRINGHASH>::Find+0x86 [D:\a\_work\1\s\src\coreclr\inc\utilcode.h @ 2683]
coreclr!StgStringPool::AddString+0x7c [D:\a\_work\1\s\src\coreclr\utilcode\stgpool.cpp @ 922]
coreclr!MetaData::StringHeapRW::AddString+0xc [D:\a\_work\1\s\src\coreclr\md\heaps\stringheap.h @ 225]
coreclr!CMiniMdRW::PutString+0x49 [D:\a\_work\1\s\src\coreclr\md\enc\metamodelrw.cpp @ 4197]
coreclr!RegMeta::DefineField+0x1ce [D:\a\_work\1\s\src\coreclr\md\compiler\emit.cpp @ 2609]
coreclr!TypeBuilder_DefineField+0x94 [D:\a\_work\1\s\src\coreclr\vm\comdynamic.cpp @ 240]
System_Private_CoreLib!System.Reflection.Emit.RuntimeFieldBuilder..ctor+0x1a4
System_Private_CoreLib!System.Reflection.Emit.RuntimeTypeBuilder.DefineFieldCore+0xbb
System_Private_CoreLib!System.Reflection.Emit.TypeBuilder.DefineField+0x19
JetBrains_RdFramework_Reflection!JetBrains.Rd.Reflection.ProxyGenerator.ImplementProperty+0xe6
More specifically, it got stuck in this loop: https://github.com/dotnet/runtime/blob/v9.0.8/src/coreclr/inc/utilcode.h#L2681-L2686
I captured a memory dump and was able to inspect the m_rgData table
index => iNext
0 => 28,
1 => 43,
2 => 38,
3 => 42,
4 => 36,
5 => 45,
6 => 40,
7 => 31,
8 => 39,
9 => 44,
10 => 4294967295,
11 => 4294967295,
12 => 4294967295,
13 => 11,
14 => 12,
15 => 10,
16 => 14,
17 => 4294967295,
18 => 4294967295,
19 => 15,
20 => 4294967295,
21 => 16,
22 => 4294967295,
23 => 18,
24 => 20,
25 => 23,
26 => 29,
27 => 13,
28 => 21,
29 => 19,
30 => 17,
31 => 31,
32 => 4294967295,
33 => 26,
34 => 27,
35 => 30,
36 => 22,
37 => 4294967295,
38 => 25,
39 => 4294967295,
40 => 35,
41 => 34,
42 => 24,
43 => 33,
44 => 37,
45 => 41,
46 => 47,
47 => 48,
48 => 4294967295,
For index 31, iNext is 31, which explains the infinite loop.
Unfortunately I don't know how the process got in that state, and I can't reproduce the issue. The dotTrace profiler was active, it was targeting another process but it's possible it activated some ETW sources that could somehow impact the behavior.
I can share the memory dump if it helps.
Reproduction Steps
Unfortunately I don't have a repro.
Expected behavior
System.Reflection.Emit.TypeBuilder.DefineField should complete normally.
Actual behavior
The call got stuck in an infinite loop in CChainedHash<STRINGHASH>::Find.
Regression?
No response
Known Workarounds
No response
Configuration
Windows 11 (x64)
.NET 9.0.8
Other information
No response
Activity
janvorli commentedon Sep 23, 2025
cc: @davidwrighton
dotnet-policy-service commentedon Sep 23, 2025
Tagging subscribers to this area: @dotnet/area-system-reflection-emit
See info in area-owners.md if you want to be subscribed.
kevingosse commentedon Sep 25, 2025
We just had a crash reported by a user, involving the same hashtable.
The crash is an access violation in
CChainedHash<STRINGHASH>::Find, more specifically:At the time of the crash,
m_iFreeis garbage (0x4EE01367).One interesting thing is that windbg reports some heap corruption:
To try to see if the corruption was caused by a buffer overrun, I inspected the previous heap block:
0x235835bfbc0 - 0x110 = 0x235835bfab0
The UserPtr of this block (
00000235835bfac0) is the same address asm_rgData.Digging further,
m_iSizeis 33. Storing 33 entries would require 33*8=264=0x108 bytes of memory. But the heap block is only 0x100 bytes, so the last entry overwrote the header of the next heap block, causing the corrupted heap error.This does not explain the garbage value in
m_iFree, but clearly there's something wrong going on.kevingosse commentedon Sep 25, 2025
I have the feeling that it's a race condition somewhere, so I've been reviewing the locking patterns in the calls to
CChainedHash<STRINGHASH>::ReHash. In most cases I see a call to the macroLOCKWRITE, however I don't see it in this call chain:Is that expected? Is there another locking mechanism that I missed?
jkotas commentedon Sep 25, 2025
Yes, that looks like a problem. Would you be interested in submitting a PR with the fix?
kevingosse commentedon Sep 26, 2025
I managed to build a repro, so I confirm that
TranslateSigHelperwas indeed the problem.Repro: https://gist.github.com/kevingosse/eff57610ed6f807b148c3f4b748a1d65 (it requires the JetBrains.RdFramework.Reflection nuget package).
I've implemented a fix and verified that it doesn't crash anymore: #120143
rizi commentedon Sep 26, 2025
@kevingosse thx for fixing this issue, @jkotas in which version of net will this fix be available?
Br
jkotas commentedon Sep 27, 2025
I have proposed backport to .NET 10