Skip to content

Commit

Permalink
Ensure Array.Resize creates an array of the same type as the incomi…
Browse files Browse the repository at this point in the history
…ng array
  • Loading branch information
xtqqczze committed Feb 27, 2024
1 parent 8bdbf99 commit cc38a59
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 8 deletions.
28 changes: 22 additions & 6 deletions src/libraries/System.Private.CoreLib/src/System/Array.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,33 @@ public static void Resize<T>([NotNull] ref T[]? array, int newSize)

if (larray.Length != newSize)
{
// Due to array variance, it's possible that the incoming array is
// actually of type U[], where U:T; or that an int[] <-> uint[] or
// similar cast has occurred. In any case, since it's always legal
// to reinterpret U as T in this scenario (but not necessarily the
// other way around), we can use SpanHelpers.Memmove here.
T[] newArray;

if (larray.GetType() == typeof(T[]))
{
// We know the type of the array to be exactly T[].

newArray = new T[newSize];
}
else
{
// The array is actually a U[] where U:T. We'll make sure to create
// an array of the exact same backing type. The cast to T[] will
// never fail.

newArray = Unsafe.As<T[]>(Array.CreateInstanceFromArrayType(larray.GetType(), newSize));
}

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

T[] newArray = new T[newSize];
Buffer.Memmove(
ref MemoryMarshal.GetArrayDataReference(newArray),
ref MemoryMarshal.GetArrayDataReference(larray),
(uint)Math.Min(newSize, larray.Length));

array = newArray;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public static T[] GetSubArray<T>(T[] array, Range range)

T[] dest;

if (typeof(T[]) == array.GetType())
if (array.GetType() == typeof(T[]))
{
// We know the type of the array to be exactly T[].

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

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

Expand Down

1 comment on commit cc38a59

@xtqqczze
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please # to comment.