Skip to content

Commit

Permalink
[mono] Fix downcast check in Array.CopySlow (#64469)
Browse files Browse the repository at this point in the history
* Add regression test for object[] -> Int32Enum[] array copy

where each element in the source array is the appropriate type

* Fix downcast check in slow array copy

When we have to resort to checking element by element, compare the type of each
actual element with the destination type. In particular, not the destinations
underlying type when it's an enum - we don't want to allow unrelated enums
using the same representation to copy over.

Fixes #64387
  • Loading branch information
lambdageek committed Jan 30, 2022
1 parent ee390ff commit bc6d349
Show file tree
Hide file tree
Showing 2 changed files with 5 additions and 4 deletions.
3 changes: 3 additions & 0 deletions src/libraries/System.Runtime/tests/System/ArrayTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1275,6 +1275,9 @@ public static IEnumerable<object[]> Copy_SZArray_UnreliableConversion_CanPerform

// Interface[] -> Class[]
yield return new object[] { new NonGenericInterface1[10], 0, new NonGenericClass1[10], 0, 10, new NonGenericClass1[10] };

// object[] -> Int32Enum[] when values are all Int32Enum
yield return new object[] { new object[] { Int32Enum.Case3 }, 0, new Int32Enum[1], 0, 1, new Int32Enum[] { Int32Enum.Case3 } };
}

public static IEnumerable<object[]> Copy_Array_UnreliableConversion_CanPerform_TestData()
Expand Down
6 changes: 2 additions & 4 deletions src/mono/System.Private.CoreLib/src/System/Array.Mono.cs
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ private static void CopySlow(Array sourceArray, int sourceIndex, Array destinati

Type src_type = sourceArray.GetType().GetElementType()!;
Type dst_type = destinationArray.GetType().GetElementType()!;
Type dst_elem_type = dst_type;
bool dst_type_vt = dst_type.IsValueType && Nullable.GetUnderlyingType(dst_type) == null;

bool src_is_enum = src_type.IsEnum;
Expand Down Expand Up @@ -199,12 +200,9 @@ private static void CopySlow(Array sourceArray, int sourceIndex, Array destinati
{
object srcval = sourceArray.GetValueImpl(source_pos + i);

if (!src_type.IsValueType && dst_is_enum)
if (dst_type_vt && (srcval == null || (src_type == typeof(object) && !dst_elem_type.IsAssignableFrom (srcval.GetType()))))
throw new InvalidCastException(SR.InvalidCast_DownCastArrayElement);

if (dst_type_vt && (srcval == null || (src_type == typeof(object) && srcval.GetType() != dst_type)))
throw new InvalidCastException();

try
{
destinationArray.SetValueRelaxedImpl(srcval, dest_pos + i);
Expand Down

0 comments on commit bc6d349

Please sign in to comment.