Skip to content

Add LOCKREADIFFAILRET to unlocked MDInternalRW read methods#127958

Open
kevingosse wants to merge 2 commits intodotnet:mainfrom
kevingosse:fix/mdinternalrw-lockread
Open

Add LOCKREADIFFAILRET to unlocked MDInternalRW read methods#127958
kevingosse wants to merge 2 commits intodotnet:mainfrom
kevingosse:fix/mdinternalrw-lockread

Conversation

@kevingosse
Copy link
Copy Markdown
Contributor

Several read methods in MDInternalRW skip locking because they assume row contents are never modified. However, ExpandTables() reallocates the backing buffer of every metadata table, invalidating pointers returned by GetMethodRecord/GetFieldRecord/GetMemberRefRecord.

This races with profiler emit operations (DefineMemberRef, etc.) that trigger ExpandTables under LOCKWRITE, causing use-after-free reads that manifest as sporadic MissingMethodException or segmentation faults.

Fix: add LOCKREADIFFAILRET() to GetSigOfMethodDef, GetSigOfFieldDef, GetNameAndSigOfMemberRef, and GetSigFromToken.

Fixes #127957

Several read methods in MDInternalRW skip locking because they
assume row contents are never modified. However, ExpandTables()
reallocates the backing buffer of every metadata table, invalidating
pointers returned by GetMethodRecord/GetFieldRecord/GetMemberRefRecord.

This races with profiler emit operations (DefineMemberRef, etc.) that
trigger ExpandTables under LOCKWRITE, causing use-after-free reads
that manifest as sporadic MissingMethodException or access violations.

Fix: add LOCKREADIFFAILRET() to GetSigOfMethodDef, GetSigOfFieldDef,
GetNameAndSigOfMemberRef, and GetSigFromToken.
Copilot AI review requested due to automatic review settings May 8, 2026 14:30
@dotnet-policy-service dotnet-policy-service Bot added the community-contribution Indicates that the PR has been added by a community member label May 8, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds read-locking to metadata signature/name accessors and simplifies error handling to return directly instead of using ErrExit/IfFailGo.

Changes:

  • Add LOCKREADIFFAILRET() in GetSigOfMethodDef, GetSigOfFieldDef, and GetNameAndSigOfMemberRef.
  • In GetSigFromToken, acquire read locks for mdtSignature/mdtTypeSpec and replace IfFailGo + ErrExit with IfFailRet + direct returns.
  • Simplify invalid-token handling by returning META_E_INVALID_TOKEN_TYPE directly.

Comment thread src/coreclr/md/enc/mdinternalrw.cpp Outdated
Comment on lines 2287 to 2291
HRESULT hr;
// We don't change MethodDef signature. No need to lock.
LOCKREADIFFAILRET();

MethodRec *pMethodRec;
*ppSig = NULL;
Comment thread src/coreclr/md/enc/mdinternalrw.cpp Outdated
Comment on lines 2312 to 2316
HRESULT hr;
// We don't change Field's signature. No need to lock.
LOCKREADIFFAILRET();

FieldRec *pFieldRec;
*ppSig = NULL;
@@ -2332,34 +2332,35 @@ MDInternalRW::GetSigFromToken(
PCCOR_SIGNATURE * ppSig)
{
HRESULT hr;
@@ -2669,8 +2667,7 @@ MDInternalRW::GetNameAndSigOfMemberRef( // meberref's name
LPCSTR *pszMemberRefName)
{
HRESULT hr;
@steveisok steveisok requested a review from a team May 8, 2026 14:46
@dotnet-policy-service
Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @steveisok, @tommcdon, @dotnet/dotnet-diag
See info in area-owners.md if you want to be subscribed.

Address review feedback: if LOCKREADIFFAILRET fails, callers should
still see deterministic out-param values (NULL/0) rather than
uninitialized memory. Move out-param initialization above the lock.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-Diagnostics-coreclr community-contribution Indicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Race condition in MDInternalRW

3 participants