Skip to content

Commit

Permalink
[release/6.0] [mono] Fix downcast check in Array.CopySlow (dotnet#64479)
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 dotnet#64387

Co-authored-by: Aleksey Kliger <alklig@microsoft.com>
  • Loading branch information
github-actions[bot] and lambdageek authored Feb 7, 2022
1 parent 9271e5a commit c849005
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 @@ -164,6 +164,7 @@ private static void Copy(Array sourceArray, int sourceIndex, Array destinationAr

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 @@ -196,12 +197,9 @@ private static void Copy(Array sourceArray, int sourceIndex, Array destinationAr
{
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 c849005

Please sign in to comment.