Skip to content

Commit cc38a59

Browse files
committed
Ensure Array.Resize creates an array of the same type as the incoming array
1 parent 8bdbf99 commit cc38a59

File tree

2 files changed

+24
-8
lines changed

2 files changed

+24
-8
lines changed

src/libraries/System.Private.CoreLib/src/System/Array.cs

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,17 +54,33 @@ public static void Resize<T>([NotNull] ref T[]? array, int newSize)
5454

5555
if (larray.Length != newSize)
5656
{
57-
// Due to array variance, it's possible that the incoming array is
58-
// actually of type U[], where U:T; or that an int[] <-> uint[] or
59-
// similar cast has occurred. In any case, since it's always legal
60-
// to reinterpret U as T in this scenario (but not necessarily the
61-
// other way around), we can use SpanHelpers.Memmove here.
57+
T[] newArray;
58+
59+
if (larray.GetType() == typeof(T[]))
60+
{
61+
// We know the type of the array to be exactly T[].
62+
63+
newArray = new T[newSize];
64+
}
65+
else
66+
{
67+
// The array is actually a U[] where U:T. We'll make sure to create
68+
// an array of the exact same backing type. The cast to T[] will
69+
// never fail.
70+
71+
newArray = Unsafe.As<T[]>(Array.CreateInstanceFromArrayType(larray.GetType(), newSize));
72+
}
73+
74+
// In either case, the newly-allocated array is the exact same type as the
75+
// original incoming array. It's safe for us to Buffer.Memmove the contents
76+
// from the source array to the destination array, otherwise the contents
77+
// wouldn't have been valid for the source array in the first place.
6278

63-
T[] newArray = new T[newSize];
6479
Buffer.Memmove(
6580
ref MemoryMarshal.GetArrayDataReference(newArray),
6681
ref MemoryMarshal.GetArrayDataReference(larray),
6782
(uint)Math.Min(newSize, larray.Length));
83+
6884
array = newArray;
6985
}
7086

src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public static T[] GetSubArray<T>(T[] array, Range range)
2929

3030
T[] dest;
3131

32-
if (typeof(T[]) == array.GetType())
32+
if (array.GetType() == typeof(T[]))
3333
{
3434
// We know the type of the array to be exactly T[].
3535

@@ -50,7 +50,7 @@ public static T[] GetSubArray<T>(T[] array, Range range)
5050
}
5151

5252
// In either case, the newly-allocated array is the exact same type as the
53-
// original incoming array. It's safe for us to SpanHelpers.Memmove the contents
53+
// original incoming array. It's safe for us to Buffer.Memmove the contents
5454
// from the source array to the destination array, otherwise the contents
5555
// wouldn't have been valid for the source array in the first place.
5656

0 commit comments

Comments
 (0)