Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 19b74c1

Browse files
authored
[release/2.0.x] Fix built-in GetHashCode crash on nested structs (#17720)
Fixes #17661
1 parent 2e651d0 commit 19b74c1

File tree

1 file changed

+11
-8
lines changed

1 file changed

+11
-8
lines changed

src/vm/comutilnative.cpp

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2688,13 +2688,14 @@ static INT32 RegularGetValueTypeHashCode(MethodTable *mt, void *pObjRef)
26882688
} CONTRACTL_END;
26892689

26902690
INT32 hashCode = 0;
2691-
INT32 *pObj = (INT32*)pObjRef;
2691+
2692+
GCPROTECT_BEGININTERIOR(pObjRef);
26922693

26932694
// While we shouln't get here directly from ValueTypeHelper::GetHashCode, if we recurse we need to
26942695
// be able to handle getting the hashcode for an embedded structure whose hashcode is computed by the fast path.
26952696
if (CanUseFastGetHashCodeHelper(mt))
26962697
{
2697-
return FastGetValueTypeHashCodeHelper(mt, pObjRef);
2698+
hashCode = FastGetValueTypeHashCodeHelper(mt, pObjRef);
26982699
}
26992700
else
27002701
{
@@ -2715,13 +2716,13 @@ static INT32 RegularGetValueTypeHashCode(MethodTable *mt, void *pObjRef)
27152716
{
27162717
FieldDesc *field = fdIterator.Next();
27172718
_ASSERTE(!field->IsRVA());
2718-
void *pFieldValue = (BYTE *)pObj + field->GetOffsetUnsafe();
27192719
if (field->IsObjRef())
27202720
{
2721+
void *pFieldValue = (BYTE *)pObjRef + field->GetOffsetUnsafe();
2722+
27212723
// if we get an object reference we get the hash code out of that
27222724
if (*(Object**)pFieldValue != NULL)
27232725
{
2724-
27252726
OBJECTREF fieldObjRef = ObjectToOBJECTREF(*(Object **) pFieldValue);
27262727
GCPROTECT_BEGIN(fieldObjRef);
27272728

@@ -2741,26 +2742,28 @@ static INT32 RegularGetValueTypeHashCode(MethodTable *mt, void *pObjRef)
27412742
}
27422743
else
27432744
{
2744-
UINT fieldSize = field->LoadSize();
2745-
INT32 *pValue = (INT32*)pFieldValue;
27462745
CorElementType fieldType = field->GetFieldType();
27472746
if (fieldType != ELEMENT_TYPE_VALUETYPE)
27482747
{
2748+
UINT fieldSize = field->LoadSize();
2749+
INT32 *pValue = (INT32*)((BYTE *)pObjRef + field->GetOffsetUnsafe());
27492750
for (INT32 j = 0; j < (INT32)(fieldSize / sizeof(INT32)); j++)
27502751
hashCode ^= *pValue++;
27512752
}
27522753
else
27532754
{
27542755
// got another value type. Get the type
2755-
TypeHandle fieldTH = field->LookupFieldTypeHandle(); // the type was loaded already
2756+
TypeHandle fieldTH = field->GetFieldTypeHandleThrowing();
27562757
_ASSERTE(!fieldTH.IsNull());
2757-
hashCode = RegularGetValueTypeHashCode(fieldTH.GetMethodTable(), pValue);
2758+
hashCode = RegularGetValueTypeHashCode(fieldTH.GetMethodTable(), (BYTE *)pObjRef + field->GetOffsetUnsafe());
27582759
}
27592760
}
27602761
break;
27612762
}
27622763
}
27632764
}
2765+
GCPROTECT_END();
2766+
27642767
return hashCode;
27652768
}
27662769

0 commit comments

Comments
 (0)