From f52617bdb42de7edfbed8d70148e73b42553982c Mon Sep 17 00:00:00 2001 From: Steve Pfister Date: Tue, 14 Jul 2026 10:19:12 -0400 Subject: [PATCH] Fix concurrent Reflection.Emit TypeLoadException (#129230) PR #125536 added an AddPropertyToLookUpTable call inside CMiniMdRW::AddPropertyToPropertyMap (and AddEventToLookUpTable inside AddEventToEventMap) so that the ENC/hot-reload path, which reaches those functions via metamodelenc.cpp rather than RegMeta::DefineProperty, would also maintain the property/event parent lookup table (fixing #125534). However the emit path already appended to the lookup table: DefineProperty and _DefineEvent call AddPropertyToPropertyMap/AddEventToEventMap and then also call Add*ToLookUpTable themselves, gated on HasIndirectTable. The S_FALSE branch in AddPropertyToPropertyMap fires under exactly the same condition (an indirect PropertyPtr/EventPtr table exists), so after #125536 the emit path appended the same entry twice. Add*ToLookUpTable only appends once the lazily-built lookup map is non-NULL (the map is built on demand by a reader in FindParentOf*Helper). When a concurrent reader has built the map, the duplicate append desyncs the map's Count from the member RID, so a subsequently emitted member is recorded against the wrong parent typedef, surfacing as a TypeLoadException. This is why the regression only reproduces under concurrent emit + reflection. Remove the now-redundant emit-side appends so the lookup table is maintained in exactly one place (AddPropertyToPropertyMap/AddEventToEventMap), which serves both the emit and ENC/hot-reload callers and preserves the #125534 fix. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- src/coreclr/md/compiler/emit.cpp | 4 ---- src/coreclr/md/compiler/regmeta_emit.cpp | 4 ---- 2 files changed, 8 deletions(-) diff --git a/src/coreclr/md/compiler/emit.cpp b/src/coreclr/md/compiler/emit.cpp index 4477d55c215e2f..6394b4918d86b0 100644 --- a/src/coreclr/md/compiler/emit.cpp +++ b/src/coreclr/md/compiler/emit.cpp @@ -2751,10 +2751,6 @@ HRESULT RegMeta::DefineProperty( IfFailGo(_SetPropertyProps(*pmdProp, dwPropFlags, dwCPlusTypeFlag, pValue, cchValue, mdSetter, mdGetter, rmdOtherMethods)); - // Add the to the lookup table - if (m_pStgdb->m_MiniMd.HasIndirectTable(TBL_Property)) - IfFailGo( m_pStgdb->m_MiniMd.AddPropertyToLookUpTable(*pmdProp, td) ); - ErrExit: SetCallerExternal(); diff --git a/src/coreclr/md/compiler/regmeta_emit.cpp b/src/coreclr/md/compiler/regmeta_emit.cpp index 4a33c52245b64e..c53a45261b3826 100644 --- a/src/coreclr/md/compiler/regmeta_emit.cpp +++ b/src/coreclr/md/compiler/regmeta_emit.cpp @@ -1333,10 +1333,6 @@ HRESULT RegMeta::_DefineEvent( // Return hresult. IfFailGo(m_pStgdb->m_MiniMd.PutString(TBL_Event, EventRec::COL_Name, pEventRec, szUTF8Event)); IfFailGo(_SetEventProps1(*pmdEvent, dwEventFlags, tkEventType)); - // Add the to the lookup table - if (m_pStgdb->m_MiniMd.HasIndirectTable(TBL_Event)) - IfFailGo( m_pStgdb->m_MiniMd.AddEventToLookUpTable(*pmdEvent, td) ); - IfFailGo(UpdateENCLog(*pmdEvent)); ErrExit: