Skip to content

Commit edfa1d5

Browse files
github-actions[bot]kevingossenoahfalk
authored
[release/10.0] Add LOCKREADIFFAILRET to unlocked MDInternalRW read methods (#128671)
Backport of #127958 to release/10.0 /cc @elinor-fung @kevingosse ## Customer Impact - [x] Customer reported - [ ] Found internally Issue: #127957 Some read operations for metadata tables were not done under a lock. When the tables are expanded - for example via profiler emit operations - concurrent reads can end up with invalid pointers resulting in a segfault or a MissingMethodException. DataDog has been hitting it multiple times a week in CI and has gotten customer reports as well. ## Regression - [ ] Yes - [x] No ## Testing @andrewlock validated against CI that was hitting this issue without this fix: #127958 (comment) @kevingosse validated against local changes that were reproing the issue before his fix: #127958 (comment) ## Risk Low. --------- Co-authored-by: Kevin Gosse <krix33@gmail.com> Co-authored-by: Noah Falk <noahfalk@microsoft.com>
1 parent 2c77e2c commit edfa1d5

1 file changed

Lines changed: 91 additions & 33 deletions

File tree

src/coreclr/md/enc/mdinternalrw.cpp

Lines changed: 91 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1566,10 +1566,13 @@ MDInternalRW::GetCustomAttributeProps( // S_OK or error.
15661566
mdToken *pTkType) // Put attribute type here.
15671567
{
15681568
HRESULT hr;
1569-
// Getting the custom value prop with a token, no need to lock!
15701569

15711570
_ASSERTE(TypeFromToken(at) == mdtCustomAttribute);
15721571

1572+
*pTkType = mdTokenNil;
1573+
1574+
LOCKREADIFFAILRET();
1575+
15731576
// Do a linear search on compressed version as we do not want to
15741577
// depend on ICR.
15751578
//
@@ -1591,10 +1594,14 @@ MDInternalRW::GetCustomAttributeAsBlob(
15911594
void const **ppBlob, // [OUT] return the pointer to internal blob
15921595
ULONG *pcbSize) // [OUT] return the size of the blob
15931596
{
1594-
// Getting the custom value prop with a token, no need to lock!
15951597
HRESULT hr;
15961598
_ASSERTE(ppBlob && pcbSize && TypeFromToken(cv) == mdtCustomAttribute);
15971599

1600+
*ppBlob = NULL;
1601+
*pcbSize = 0;
1602+
1603+
LOCKREADIFFAILRET();
1604+
15981605
CustomAttributeRec *pCustomAttributeRec;
15991606

16001607
IfFailRet(m_pStgdb->m_MiniMd.GetCustomAttributeRecord(RidFromToken(cv), &pCustomAttributeRec));
@@ -1805,7 +1812,6 @@ MDInternalRW::GetNameOfTypeDef( // return hresult
18051812
LPCSTR* pszname, // pointer to an internal UTF8 string
18061813
LPCSTR* psznamespace) // pointer to the namespace.
18071814
{
1808-
// No need to lock this method.
18091815
HRESULT hr;
18101816

18111817
if (pszname != NULL)
@@ -1819,6 +1825,8 @@ MDInternalRW::GetNameOfTypeDef( // return hresult
18191825

18201826
if (TypeFromToken(classdef) == mdtTypeDef)
18211827
{
1828+
LOCKREADIFFAILRET();
1829+
18221830
TypeDefRec *pTypeDefRec;
18231831
IfFailRet(m_pStgdb->m_MiniMd.GetTypeDefRecord(RidFromToken(classdef), &pTypeDefRec));
18241832

@@ -1898,10 +1906,12 @@ MDInternalRW::GetNameOfMethodDef(
18981906
mdMethodDef md,
18991907
LPCSTR *pszMethodName)
19001908
{
1901-
// name of method will not change. So no need to lock
19021909
HRESULT hr;
1903-
MethodRec *pMethodRec;
19041910
*pszMethodName = NULL;
1911+
1912+
LOCKREADIFFAILRET();
1913+
1914+
MethodRec *pMethodRec;
19051915
IfFailRet(m_pStgdb->m_MiniMd.GetMethodRecord(RidFromToken(md), &pMethodRec));
19061916
IfFailRet(m_pStgdb->m_MiniMd.getNameOfMethod(pMethodRec, pszMethodName));
19071917
return S_OK;
@@ -1920,20 +1930,23 @@ MDInternalRW::GetNameAndSigOfMethodDef(
19201930
LPCSTR *pszMethodName)
19211931
{
19221932
HRESULT hr;
1923-
// we don't need lock here because name and signature will not change
19241933

19251934
// Output parameter should not be NULL
19261935
_ASSERTE(ppvSigBlob && pcbSigBlob);
19271936
_ASSERTE(TypeFromToken(methoddef) == mdtMethodDef);
19281937

1929-
MethodRec *pMethodRec;
19301938
*pszMethodName = NULL;
19311939
*ppvSigBlob = NULL;
1932-
*ppvSigBlob = NULL;
1940+
*pcbSigBlob = 0;
1941+
1942+
LOCKREADIFFAILRET();
1943+
1944+
MethodRec *pMethodRec;
19331945
IfFailRet(m_pStgdb->m_MiniMd.GetMethodRecord(RidFromToken(methoddef), &pMethodRec));
19341946
IfFailRet(m_pStgdb->m_MiniMd.getSignatureOfMethod(pMethodRec, ppvSigBlob, pcbSigBlob));
1947+
IfFailRet(m_pStgdb->m_MiniMd.getNameOfMethod(pMethodRec, pszMethodName));
19351948

1936-
return GetNameOfMethodDef(methoddef, pszMethodName);
1949+
return S_OK;
19371950
} // MDInternalRW::GetNameAndSigOfMethodDef
19381951

19391952

@@ -1946,11 +1959,12 @@ MDInternalRW::GetNameOfFieldDef( // return hresult
19461959
mdFieldDef fd, // given field
19471960
LPCSTR *pszFieldName)
19481961
{
1949-
// we don't need lock here because name of field will not change
19501962
HRESULT hr;
1963+
*pszFieldName = NULL;
1964+
1965+
LOCKREADIFFAILRET();
19511966

19521967
FieldRec *pFieldRec;
1953-
*pszFieldName = NULL;
19541968
IfFailRet(m_pStgdb->m_MiniMd.GetFieldRecord(RidFromToken(fd), &pFieldRec));
19551969
IfFailRet(m_pStgdb->m_MiniMd.getNameOfField(pFieldRec, pszFieldName));
19561970
return S_OK;
@@ -1973,7 +1987,7 @@ MDInternalRW::GetNameOfTypeRef( // return TypeDef's name
19731987
*psznamespace = NULL;
19741988
*pszname = NULL;
19751989

1976-
// we don't need lock here because name of a typeref will not change
1990+
LOCKREADIFFAILRET();
19771991

19781992
TypeRefRec *pTypeRefRec;
19791993
IfFailRet(m_pStgdb->m_MiniMd.GetTypeRefRecord(RidFromToken(classref), &pTypeRefRec));
@@ -2196,6 +2210,8 @@ MDInternalRW::GetCountNestedClasses( // return count of Nested classes.
21962210

21972211
*pcNestedClassesCount = 0;
21982212

2213+
LOCKREADIFFAILRET();
2214+
21992215
ulCount = m_pStgdb->m_MiniMd.getCountNestedClasss();
22002216

22012217
for (ULONG i = 1; i <= ulCount; i++)
@@ -2229,6 +2245,8 @@ MDInternalRW::GetNestedClasses( // Return actual count.
22292245

22302246
*pcNestedClasses = 0;
22312247

2248+
LOCKREADIFFAILRET();
2249+
22322250
ulCount = m_pStgdb->m_MiniMd.getCountNestedClasss();
22332251

22342252
for (ULONG i = 1; i <= ulCount; i++)
@@ -2285,11 +2303,12 @@ MDInternalRW::GetSigOfMethodDef(
22852303
_ASSERTE(TypeFromToken(methoddef) == mdtMethodDef);
22862304

22872305
HRESULT hr;
2288-
// We don't change MethodDef signature. No need to lock.
2289-
2290-
MethodRec *pMethodRec;
22912306
*ppSig = NULL;
22922307
*pcbSigBlob = 0;
2308+
2309+
LOCKREADIFFAILRET();
2310+
2311+
MethodRec *pMethodRec;
22932312
IfFailRet(m_pStgdb->m_MiniMd.GetMethodRecord(RidFromToken(methoddef), &pMethodRec));
22942313
IfFailRet(m_pStgdb->m_MiniMd.getSignatureOfMethod(pMethodRec, ppSig, pcbSigBlob));
22952314
return S_OK;
@@ -2310,11 +2329,12 @@ MDInternalRW::GetSigOfFieldDef(
23102329
_ASSERTE(TypeFromToken(fielddef) == mdtFieldDef);
23112330

23122331
HRESULT hr;
2313-
// We don't change Field's signature. No need to lock.
2314-
2315-
FieldRec *pFieldRec;
23162332
*ppSig = NULL;
23172333
*pcbSigBlob = 0;
2334+
2335+
LOCKREADIFFAILRET();
2336+
2337+
FieldRec *pFieldRec;
23182338
IfFailRet(m_pStgdb->m_MiniMd.GetFieldRecord(RidFromToken(fielddef), &pFieldRec));
23192339
IfFailRet(m_pStgdb->m_MiniMd.getSignatureOfField(pFieldRec, ppSig, pcbSigBlob));
23202340
return S_OK;
@@ -2332,34 +2352,35 @@ MDInternalRW::GetSigFromToken(
23322352
PCCOR_SIGNATURE * ppSig)
23332353
{
23342354
HRESULT hr;
2335-
// We don't change token's signature. Thus no need to lock.
23362355

23372356
*ppSig = NULL;
23382357
*pcbSig = 0;
23392358
switch (TypeFromToken(tk))
23402359
{
23412360
case mdtSignature:
23422361
{
2362+
LOCKREADIFFAILRET();
23432363
StandAloneSigRec *pRec;
2344-
IfFailGo(m_pStgdb->m_MiniMd.GetStandAloneSigRecord(RidFromToken(tk), &pRec));
2345-
IfFailGo(m_pStgdb->m_MiniMd.getSignatureOfStandAloneSig(pRec, ppSig, pcbSig));
2364+
IfFailRet(m_pStgdb->m_MiniMd.GetStandAloneSigRecord(RidFromToken(tk), &pRec));
2365+
IfFailRet(m_pStgdb->m_MiniMd.getSignatureOfStandAloneSig(pRec, ppSig, pcbSig));
23462366
return S_OK;
23472367
}
23482368
case mdtTypeSpec:
23492369
{
2370+
LOCKREADIFFAILRET();
23502371
TypeSpecRec *pRec;
2351-
IfFailGo(m_pStgdb->m_MiniMd.GetTypeSpecRecord(RidFromToken(tk), &pRec));
2352-
IfFailGo(m_pStgdb->m_MiniMd.getSignatureOfTypeSpec(pRec, ppSig, pcbSig));
2372+
IfFailRet(m_pStgdb->m_MiniMd.GetTypeSpecRecord(RidFromToken(tk), &pRec));
2373+
IfFailRet(m_pStgdb->m_MiniMd.getSignatureOfTypeSpec(pRec, ppSig, pcbSig));
23532374
return S_OK;
23542375
}
23552376
case mdtMethodDef:
23562377
{
2357-
IfFailGo(GetSigOfMethodDef(tk, pcbSig, ppSig));
2378+
IfFailRet(GetSigOfMethodDef(tk, pcbSig, ppSig));
23582379
return S_OK;
23592380
}
23602381
case mdtFieldDef:
23612382
{
2362-
IfFailGo(GetSigOfFieldDef(tk, pcbSig, ppSig));
2383+
IfFailRet(GetSigOfFieldDef(tk, pcbSig, ppSig));
23632384
return S_OK;
23642385
}
23652386
}
@@ -2370,10 +2391,7 @@ MDInternalRW::GetSigFromToken(
23702391
_ASSERTE(!"Unexpected token type");
23712392
#endif
23722393
*pcbSig = 0;
2373-
hr = META_E_INVALID_TOKEN_TYPE;
2374-
2375-
ErrExit:
2376-
return hr;
2394+
return META_E_INVALID_TOKEN_TYPE;
23772395
} // MDInternalRW::GetSigFromToken
23782396

23792397

@@ -2584,12 +2602,13 @@ MDInternalRW::GetTypeOfInterfaceImpl( // return hresult
25842602
mdToken *ptkType)
25852603
{
25862604
HRESULT hr;
2587-
// no need to lock this function.
25882605

25892606
_ASSERTE(TypeFromToken(iiImpl) == mdtInterfaceImpl);
25902607

25912608
*ptkType = mdTypeDefNil;
25922609

2610+
LOCKREADIFFAILRET();
2611+
25932612
InterfaceImplRec *pIIRec;
25942613
IfFailRet(m_pStgdb->m_MiniMd.GetInterfaceImplRecord(RidFromToken(iiImpl), &pIIRec));
25952614
*ptkType = m_pStgdb->m_MiniMd.getInterfaceOfInterfaceImpl(pIIRec);
@@ -2611,6 +2630,15 @@ HRESULT MDInternalRW::GetMethodSpecProps( // S_OK or error.
26112630

26122631
_ASSERTE(TypeFromToken(mi) == mdtMethodSpec);
26132632

2633+
if (tkParent)
2634+
*tkParent = mdTokenNil;
2635+
if (ppvSigBlob)
2636+
*ppvSigBlob = NULL;
2637+
if (pcbSigBlob)
2638+
*pcbSigBlob = 0;
2639+
2640+
LOCKREADIFFAILRET();
2641+
26142642
IfFailGo(m_pStgdb->m_MiniMd.GetMethodSpecRecord(RidFromToken(mi), &pMethodSpecRec));
26152643

26162644
if (tkParent)
@@ -2670,24 +2698,26 @@ MDInternalRW::GetNameAndSigOfMemberRef( // meberref's name
26702698
{
26712699
HRESULT hr;
26722700

2673-
// MemberRef's name and sig won't change. Don't need to lock this.
2674-
26752701
_ASSERTE(TypeFromToken(memberref) == mdtMemberRef);
26762702

2677-
MemberRefRec *pMemberRefRec;
26782703
*pszMemberRefName = NULL;
26792704
if (ppvSigBlob != NULL)
26802705
{
26812706
_ASSERTE(pcbSigBlob != NULL);
26822707
*ppvSigBlob = NULL;
26832708
*pcbSigBlob = 0;
26842709
}
2710+
2711+
LOCKREADIFFAILRET();
2712+
2713+
MemberRefRec *pMemberRefRec;
26852714
IfFailRet(m_pStgdb->m_MiniMd.GetMemberRefRecord(RidFromToken(memberref), &pMemberRefRec));
26862715
if (ppvSigBlob != NULL)
26872716
{
26882717
IfFailRet(m_pStgdb->m_MiniMd.getSignatureOfMemberRef(pMemberRefRec, ppvSigBlob, pcbSigBlob));
26892718
}
26902719
IfFailRet(m_pStgdb->m_MiniMd.getNameOfMemberRef(pMemberRefRec, pszMemberRefName));
2720+
26912721
return S_OK;
26922722
} // MDInternalRW::GetNameAndSigOfMemberRef
26932723

@@ -3243,6 +3273,19 @@ HRESULT MDInternalRW::GetGenericParamProps( // S_OK or error.
32433273
HRESULT hr = NOERROR;
32443274
GenericParamRec *pGenericParamRec = NULL;
32453275

3276+
if (pulSequence)
3277+
*pulSequence = 0;
3278+
if (pdwAttr)
3279+
*pdwAttr = 0;
3280+
if (ptOwner)
3281+
*ptOwner = mdTokenNil;
3282+
if (reserved)
3283+
*reserved = 0;
3284+
if (szName != NULL)
3285+
*szName = NULL;
3286+
3287+
LOCKREADIFFAILRET();
3288+
32463289
// See if this version of the metadata can do Generics
32473290
if (!m_pStgdb->m_MiniMd.SupportsGenerics())
32483291
IfFailGo(CLDB_E_INCOMPATIBLE);
@@ -3282,6 +3325,13 @@ HRESULT MDInternalRW::GetGenericParamConstraintProps( // S_OK or error.
32823325
GenericParamConstraintRec *pGPCRec;
32833326
RID ridRD = RidFromToken(rd);
32843327

3328+
if (ptGenericParam)
3329+
*ptGenericParam = mdGenericParamNil;
3330+
if (ptkConstraintType)
3331+
*ptkConstraintType = mdTokenNil;
3332+
3333+
LOCKREADIFFAILRET();
3334+
32853335
// See if this version of the metadata can do Generics
32863336
if (!m_pStgdb->m_MiniMd.SupportsGenerics())
32873337
IfFailGo(CLDB_E_INCOMPATIBLE);
@@ -3775,9 +3825,14 @@ HRESULT MDInternalRW::GetTypeSpecFromToken( // S_OK or error.
37753825
_ASSERTE(TypeFromToken(typespec) == mdtTypeSpec);
37763826
_ASSERTE(ppvSig && pcbSig);
37773827

3828+
*ppvSig = NULL;
3829+
*pcbSig = 0;
3830+
37783831
if (!IsValidToken(typespec))
37793832
return E_INVALIDARG;
37803833

3834+
LOCKREADIFFAILRET();
3835+
37813836
TypeSpecRec *pRec;
37823837
IfFailRet(m_pStgdb->m_MiniMd.GetTypeSpecRecord(RidFromToken(typespec), &pRec));
37833838

@@ -3969,6 +4024,9 @@ HRESULT MDInternalRW::EnumDeltaTokensInit( // return hresult
39694024
phEnum->m_EnumType = MDSimpleEnum;
39704025

39714026
HENUMInternal::InitDynamicArrayEnum(phEnum);
4027+
4028+
LOCKREADIFFAILRET();
4029+
39724030
for (index = 1; index <= m_pStgdb->m_MiniMd.m_Schema.m_cRecs[TBL_ENCLog]; ++index)
39734031
{
39744032
// Get the token type; see if it is a real token.

0 commit comments

Comments
 (0)