@@ -196,6 +196,81 @@ void CLR_RT_EventCache::VirtualMethodTable::Initialize()
196196 m_entriesMRU = (Link *)&g_scratchVirtualMethodTableLinkMRU[0 ];
197197 m_payloads = (Payload *)&g_scratchVirtualMethodPayload[0 ];
198198
199+ #ifdef DEBUG
200+
201+ // DIAGNOSTIC: Verify structure sizes and alignment
202+ CLR_Debug::Printf (" \r\n ========== VirtualMethodTable::Initialize DIAGNOSTICS ==========\r\n " );
203+ CLR_Debug::Printf (" sizeof(Link) = %u, alignof(Link) = %u\r\n " , sizeof (Link), alignof (Link));
204+ CLR_Debug::Printf (" sizeof(Payload) = %u, alignof(Payload) = %u\r\n " , sizeof (Payload), alignof (Payload));
205+ CLR_Debug::Printf (" sizeof(Payload::Key) = %u\r\n " , sizeof (Payload::Key));
206+ CLR_Debug::Printf (" LinkArraySize() = %u (expected: 641)\r\n " , LinkArraySize ());
207+ CLR_Debug::Printf (" LinkMRUArraySize() = %u (expected: 513)\r\n " , LinkMRUArraySize ());
208+ CLR_Debug::Printf (" PayloadArraySize() = %u (expected: 512)\r\n " , PayloadArraySize ());
209+
210+ // Verify array base addresses don't overlap
211+ uintptr_t entries_start = (uintptr_t )m_entries;
212+ uintptr_t entries_end = entries_start + (LinkArraySize () * sizeof (Link));
213+ uintptr_t entriesMRU_start = (uintptr_t )m_entriesMRU;
214+ uintptr_t entriesMRU_end = entriesMRU_start + (LinkMRUArraySize () * sizeof (Link));
215+ uintptr_t payloads_start = (uintptr_t )m_payloads;
216+ uintptr_t payloads_end = payloads_start + (PayloadArraySize () * sizeof (Payload));
217+
218+ #ifdef _WIN64
219+
220+ CLR_Debug::Printf (
221+ " m_entries: 0x%" PRIx64 " - 0x% " PRIx64 " (%u bytes)\r\n " ,
222+ entries_start,
223+ entries_end,
224+ (unsigned int )(entries_end - entries_start));
225+ CLR_Debug::Printf (
226+ " m_entriesMRU: 0x%" PRIx64 " - 0x% " PRIx64 " (%u bytes)\r\n " ,
227+ entriesMRU_start,
228+ entriesMRU_end,
229+ (unsigned int )(entriesMRU_end - entriesMRU_start));
230+ CLR_Debug::Printf (
231+ " m_payloads: 0x% " PRIx64 " - 0x% " PRIx64 " (%u bytes)\r\n " ,
232+ payloads_start,
233+ payloads_end,
234+ (unsigned int )(payloads_end - payloads_start));
235+
236+ #else
237+
238+ CLR_Debug::Printf (
239+ " m_entries: 0x%08X - 0x%08X (%u bytes)\r\n " ,
240+ entries_start,
241+ entries_end,
242+ (unsigned int )(entries_end - entries_start));
243+ CLR_Debug::Printf (
244+ " m_entriesMRU: 0x%08X - 0x%08X (%u bytes)\r\n " ,
245+ entriesMRU_start,
246+ entriesMRU_end,
247+ (unsigned int )(entriesMRU_end - entriesMRU_start));
248+ CLR_Debug::Printf (
249+ " m_payloads: 0x%08X - 0x%08X (%u bytes)\r\n " ,
250+ payloads_start,
251+ payloads_end,
252+ (unsigned int )(payloads_end - payloads_start));
253+
254+ #endif
255+
256+ // Check for overlaps
257+ if (entries_end > entriesMRU_start && entries_start < entriesMRU_end)
258+ {
259+ CLR_Debug::Printf (" *** WARNING: m_entries and m_entriesMRU OVERLAP! ***\r\n " );
260+ }
261+ if (entries_end > payloads_start && entries_start < payloads_end)
262+ {
263+ CLR_Debug::Printf (" *** WARNING: m_entries and m_payloads OVERLAP! ***\r\n " );
264+ }
265+ if (entriesMRU_end > payloads_start && entriesMRU_start < payloads_end)
266+ {
267+ CLR_Debug::Printf (" *** WARNING: m_entriesMRU and m_payloads OVERLAP! ***\r\n " );
268+ }
269+
270+ CLR_Debug::Printf (" ================================================================\r\n\r\n " );
271+
272+ #endif
273+
199274 //
200275 // Link all the entries to themselves => no elements in the lists.
201276 //
@@ -211,6 +286,7 @@ void CLR_RT_EventCache::VirtualMethodTable::Initialize()
211286 // Link all the entries to the following one => all the elements are in the MRU list.
212287 //
213288 _ASSERTE (LinkMRUArraySize () < 0xFFFF );
289+
214290 for (index = 0 ; index < LinkMRUArraySize (); index++)
215291 {
216292 Link &lnk = m_entriesMRU[index];
@@ -301,14 +377,36 @@ bool CLR_RT_EventCache::VirtualMethodTable::FindVirtualMethod(
301377
302378 for (index = m_entries[indexHead].m_next ;; index = m_entries[index].m_next )
303379 {
380+ #if defined(DEBUG) && defined(_WIN64)
381+ CLR_Debug::Printf (" Loop: index=%u, indexHead=%u\r\n " , index, indexHead);
382+ #endif
383+
384+ // validate index before using it to prevent crashes from corrupted data
385+ if (index >= LinkArraySize ())
386+ {
387+ // !! corrupted index detected !!
388+ // // repair the hash chain and treat as cache miss
389+ m_entries[indexHead].m_next = indexHead;
390+ m_entries[indexHead].m_prev = indexHead;
391+
392+ index = indexHead;
393+ }
394+
304395 if (index != indexHead)
305396 {
397+ _ASSERTE (index < PayloadArraySize ());
398+
306399 Payload &res = m_payloads[index];
307400
308401 if (res.m_key .m_mdVirtual .data != mdVirtualData)
402+ {
309403 continue ;
404+ }
405+
310406 if (res.m_key .m_cls .data != clsData)
407+ {
311408 continue ;
409+ }
312410
313411 md = res.m_md ;
314412
@@ -317,10 +415,20 @@ bool CLR_RT_EventCache::VirtualMethodTable::FindVirtualMethod(
317415 else
318416 {
319417 if (g_CLR_RT_TypeSystem.FindVirtualMethodDef (cls, mdVirtual, md) == false )
418+ {
320419 return false ;
420+ }
321421
322422 index = GetNewEntry ();
323423
424+ #if defined(DEBUG) && defined(_WIN64)
425+ CLR_Debug::Printf (" GetNewEntry returned: %u\r\n " , index);
426+ #endif
427+
428+ // initialize the entry's links before use to prevent corruption
429+ m_entries[index].m_next = index;
430+ m_entries[index].m_prev = index;
431+
324432 Payload &res = m_payloads[index];
325433
326434 res.m_md = md;
0 commit comments