Skip to content

Commit 8ead0db

Browse files
author
Mike McLaughlin
committed
Fix VS div-by-0 in DacEnumerableHashTable code
1 parent bbf23a2 commit 8ead0db

File tree

1 file changed

+34
-32
lines changed

1 file changed

+34
-32
lines changed

src/coreclr/vm/dacenumerablehash.inl

Lines changed: 34 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -345,45 +345,47 @@ DPTR(VALUE) DacEnumerableHashTable<DAC_ENUM_HASH_ARGS>::BaseFindFirstEntryByHash
345345
do
346346
{
347347
DWORD cBuckets = GetLength(curBuckets);
348+
if (cBuckets > 0)
349+
{
350+
// Compute which bucket the entry belongs in based on the hash.
351+
// +2 to skip "length" and "next" slots
352+
DWORD dwBucket = iHash % cBuckets + SKIP_SPECIAL_SLOTS;
348353

349-
// Compute which bucket the entry belongs in based on the hash.
350-
// +2 to skip "length" and "next" slots
351-
DWORD dwBucket = iHash % cBuckets + SKIP_SPECIAL_SLOTS;
352-
353-
// Point at the first entry in the bucket chain that stores entries with the given hash code.
354-
PTR_VolatileEntry pEntry = VolatileLoadWithoutBarrier(&curBuckets[dwBucket]);
355-
TADDR expectedEndSentinel = ComputeEndSentinel(BaseEndSentinel(curBuckets), dwBucket);
354+
// Point at the first entry in the bucket chain that stores entries with the given hash code.
355+
PTR_VolatileEntry pEntry = VolatileLoadWithoutBarrier(&curBuckets[dwBucket]);
356+
TADDR expectedEndSentinel = ComputeEndSentinel(BaseEndSentinel(curBuckets), dwBucket);
356357

357-
// Walk the bucket chain one entry at a time.
358-
while (!IsEndSentinel(pEntry))
359-
{
360-
if (pEntry->m_iHashValue == iHash)
358+
// Walk the bucket chain one entry at a time.
359+
while (!IsEndSentinel(pEntry))
361360
{
362-
// We've found our match.
361+
if (pEntry->m_iHashValue == iHash)
362+
{
363+
// We've found our match.
363364

364-
// Record our current search state into the provided context so that a subsequent call to
365-
// BaseFindNextEntryByHash can pick up the search where it left off.
366-
pContext->m_pEntry = dac_cast<TADDR>(pEntry);
367-
pContext->m_curBuckets = curBuckets;
368-
pContext->m_expectedEndSentinel = dac_cast<TADDR>(expectedEndSentinel);
365+
// Record our current search state into the provided context so that a subsequent call to
366+
// BaseFindNextEntryByHash can pick up the search where it left off.
367+
pContext->m_pEntry = dac_cast<TADDR>(pEntry);
368+
pContext->m_curBuckets = curBuckets;
369+
pContext->m_expectedEndSentinel = dac_cast<TADDR>(expectedEndSentinel);
369370

370-
// Return the address of the sub-classes' embedded entry structure.
371-
return VALUE_FROM_VOLATILE_ENTRY(pEntry);
372-
}
371+
// Return the address of the sub-classes' embedded entry structure.
372+
return VALUE_FROM_VOLATILE_ENTRY(pEntry);
373+
}
373374

374-
// Move to the next entry in the chain.
375-
pEntry = VolatileLoadWithoutBarrier(&pEntry->m_pNextEntry);
376-
}
375+
// Move to the next entry in the chain.
376+
pEntry = VolatileLoadWithoutBarrier(&pEntry->m_pNextEntry);
377+
}
377378

378-
if (!AcceptableEndSentinel(pEntry, expectedEndSentinel))
379-
{
380-
// If we hit this logic, we've managed to hit a case where the linked list was in the process of being
381-
// moved to a new set of buckets while we were walking the list, and we walked part of the list of the
382-
// bucket in the old hash table (which is fine), and part of the list in the new table, which may not
383-
// be the correct bucket to walk. Most notably, the situation that can cause this will cause the list in
384-
// the old bucket to be missing items. Restart the lookup, as the linked list is unlikely to still be under
385-
// edit a second time.
386-
continue;
379+
if (!AcceptableEndSentinel(pEntry, expectedEndSentinel))
380+
{
381+
// If we hit this logic, we've managed to hit a case where the linked list was in the process of being
382+
// moved to a new set of buckets while we were walking the list, and we walked part of the list of the
383+
// bucket in the old hash table (which is fine), and part of the list in the new table, which may not
384+
// be the correct bucket to walk. Most notably, the situation that can cause this will cause the list in
385+
// the old bucket to be missing items. Restart the lookup, as the linked list is unlikely to still be under
386+
// edit a second time.
387+
continue;
388+
}
387389
}
388390

389391
// in a rare case if resize is in progress, look in the new table as well.

0 commit comments

Comments
 (0)