From fd3d9251401e58c42404c217b4cd5f08c9890494 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 7 Sep 2022 12:03:30 -0700 Subject: [PATCH] [release/7.0] Fix race condition in DacEnumerableHashTable::BaseFindNextEntryByHash (#75178) * Fix race condition in DacEnumerableHashTable::BaseFindNextEntryByHash * Use a volatile load * One more volatile load Co-authored-by: Anton Lapounov --- src/coreclr/vm/dacenumerablehash.inl | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/coreclr/vm/dacenumerablehash.inl b/src/coreclr/vm/dacenumerablehash.inl index 02024c229ca7b3..cfee7b8f684be3 100644 --- a/src/coreclr/vm/dacenumerablehash.inl +++ b/src/coreclr/vm/dacenumerablehash.inl @@ -309,8 +309,8 @@ DPTR(VALUE) DacEnumerableHashTable::BaseFindFirstEntryByHash // +2 to skip "length" and "next" slots DWORD dwBucket = iHash % cBuckets + SKIP_SPECIAL_SLOTS; - // Point at the first entry in the bucket chain which would contain any entries with the given hash code. - PTR_VolatileEntry pEntry = curBuckets[dwBucket]; + // Point at the first entry in the bucket chain that stores entries with the given hash code. + PTR_VolatileEntry pEntry = VolatileLoadWithoutBarrier(&curBuckets[dwBucket]); // Walk the bucket chain one entry at a time. while (pEntry) @@ -329,13 +329,13 @@ DPTR(VALUE) DacEnumerableHashTable::BaseFindFirstEntryByHash } // Move to the next entry in the chain. - pEntry = pEntry->m_pNextEntry; + pEntry = VolatileLoadWithoutBarrier(&pEntry->m_pNextEntry); } // in a rare case if resize is in progress, look in the new table as well. // if existing entry is not in the old table, it must be in the new // since we unlink it from old only after linking into the new. - // check for next table must hapen after we looked through the current. + // check for next table must happen after we looked through the current. VolatileLoadBarrier(); curBuckets = GetNext(curBuckets); } while (curBuckets != nullptr); @@ -367,11 +367,9 @@ DPTR(VALUE) DacEnumerableHashTable::BaseFindNextEntryByHash( PTR_VolatileEntry pVolatileEntry = dac_cast(pContext->m_pEntry); iHash = pVolatileEntry->m_iHashValue; - // Iterate over the bucket chain. - while (pVolatileEntry->m_pNextEntry) + // Iterate over the rest ot the bucket chain. + while ((pVolatileEntry = VolatileLoadWithoutBarrier(&pVolatileEntry->m_pNextEntry)) != nullptr) { - // Advance to the next entry. - pVolatileEntry = pVolatileEntry->m_pNextEntry; if (pVolatileEntry->m_iHashValue == iHash) { // Found a match on hash code. Update our find context to indicate where we got to and return @@ -381,7 +379,7 @@ DPTR(VALUE) DacEnumerableHashTable::BaseFindNextEntryByHash( } } - // check for next table must hapen after we looked through the current. + // check for next table must happen after we looked through the current. VolatileLoadBarrier(); // in a case if resize is in progress, look in the new table as well.