Skip to content

Commit ca3936b

Browse files
Fix range check in LdelemaRef (#81748)
Also made `LdelemaRef` look closer to how it looks like on the CoreCLR-JIT side. Found by Pri0 tests.
1 parent 3ff80e9 commit ca3936b

File tree

1 file changed

+30
-10
lines changed
  • src/coreclr/nativeaot/Runtime.Base/src/System/Runtime

1 file changed

+30
-10
lines changed

src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/TypeCast.cs

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -756,11 +756,11 @@ public static unsafe void StelemRef(Array array, nint index, object obj)
756756
{
757757
// TODO: If both array and obj are null, we're likely going to throw Redhawk's NullReferenceException.
758758
// This should blame the caller.
759-
throw obj.MethodTable->GetClasslibException(ExceptionIDs.NullReference);
759+
throw obj.GetMethodTable()->GetClasslibException(ExceptionIDs.NullReference);
760760
}
761761
if ((uint)index >= (uint)array.Length)
762762
{
763-
throw array.MethodTable->GetClasslibException(ExceptionIDs.IndexOutOfRange);
763+
throw array.GetMethodTable()->GetClasslibException(ExceptionIDs.IndexOutOfRange);
764764
}
765765
ref object rawData = ref Unsafe.As<byte, object>(ref Unsafe.As<RawArrayData>(array).Data);
766766
ref object element = ref Unsafe.Add(ref rawData, index);
@@ -813,24 +813,44 @@ private static unsafe void StelemRef_Helper(ref object element, MethodTable* ele
813813
}
814814
}
815815

816+
// This weird structure is for parity with CoreCLR - allows potentially to be tailcalled
817+
private static unsafe ref object ThrowArrayMismatchException(Array array)
818+
{
819+
// Throw the array type mismatch exception defined by the classlib, using the input array's MethodTable*
820+
// to find the correct classlib.
821+
throw array.GetMethodTable()->GetClasslibException(ExceptionIDs.ArrayTypeMismatch);
822+
}
823+
816824
[RuntimeExport("RhpLdelemaRef")]
817825
public static unsafe ref object LdelemaRef(Array array, nint index, IntPtr elementType)
818826
{
819-
Debug.Assert(array.GetMethodTable()->IsArray, "first argument must be an array");
827+
Debug.Assert(array is null || array.GetMethodTable()->IsArray, "first argument must be an array");
828+
829+
#if INPLACE_RUNTIME
830+
// this will throw appropriate exceptions if array is null or access is out of range.
831+
ref object element = ref Unsafe.As<ArrayElement[]>(array)[index].Value;
832+
#else
833+
if (array is null)
834+
{
835+
throw ((MethodTable*)elementType)->GetClasslibException(ExceptionIDs.NullReference);
836+
}
837+
if ((uint)index >= (uint)array.Length)
838+
{
839+
throw ((MethodTable*)elementType)->GetClasslibException(ExceptionIDs.IndexOutOfRange);
840+
}
841+
ref object rawData = ref Unsafe.As<byte, object>(ref Unsafe.As<RawArrayData>(array).Data);
842+
ref object element = ref Unsafe.Add(ref rawData, index);
843+
#endif
820844

821845
MethodTable* elemType = (MethodTable*)elementType;
822846
MethodTable* arrayElemType = array.GetMethodTable()->RelatedParameterType;
823847

824-
if (!AreTypesEquivalent(elemType, arrayElemType))
848+
if (AreTypesEquivalent(elemType, arrayElemType))
825849
{
826-
// Throw the array type mismatch exception defined by the classlib, using the input array's MethodTable*
827-
// to find the correct classlib.
828-
829-
throw array.GetMethodTable()->GetClasslibException(ExceptionIDs.ArrayTypeMismatch);
850+
return ref element;
830851
}
831852

832-
ref object rawData = ref Unsafe.As<byte, object>(ref Unsafe.As<RawArrayData>(array).Data);
833-
return ref Unsafe.Add(ref rawData, index);
853+
return ref ThrowArrayMismatchException(array);
834854
}
835855

836856
internal static unsafe bool IsDerived(MethodTable* pDerivedType, MethodTable* pBaseType)

0 commit comments

Comments
 (0)