From 2e56fca49d96eb2ff83a43557ca19bd1d122a58f Mon Sep 17 00:00:00 2001 From: Johan Laanstra Date: Mon, 30 Sep 2024 17:19:48 -0700 Subject: [PATCH] ToArray fails when buffer capacity is larger than its length. (#1805) * Add failing test for ToArray. * Add missing Slice call to limit length of span to count. * Add another test. --- .../UnitTest/TestComponentCSharp_Tests.cs | 28 +++++++++++++++++++ .../WindowsRuntimeBufferExtensions.cs | 6 ++-- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/Tests/UnitTest/TestComponentCSharp_Tests.cs b/src/Tests/UnitTest/TestComponentCSharp_Tests.cs index 15ef3f9a7..ae6008a40 100644 --- a/src/Tests/UnitTest/TestComponentCSharp_Tests.cs +++ b/src/Tests/UnitTest/TestComponentCSharp_Tests.cs @@ -459,6 +459,34 @@ public void TestEmptyBufferCopyTo() Assert.True(array.Length == 0); } + [Fact] + public void TestBufferToArrayCapacityLargerThanLength() + { + var buffer = new Windows.Storage.Streams.Buffer(100); + byte[] arr = new byte[] { 0x01, 0x02, 0x03 }; + arr.CopyTo(0, buffer, 0, 3); + + byte[] newArr = buffer.ToArray(); + Assert.True(newArr.Length == 3); + } + + [Fact] + public void TestBufferCopyToBufferCapacityLargerThanLength() + { + var buffer = new Windows.Storage.Streams.Buffer(100); + byte[] arr = new byte[] { 0x01, 0x02, 0x03 }; + arr.CopyTo(0, buffer, 0, 3); + + var buffer2 = new Windows.Storage.Streams.Buffer(50); + byte[] arr2 = new byte[] { 0x01, 0x02 }; + arr2.CopyTo(0, buffer2, 0, 2); + + Assert.True(buffer2.Length == 2); + + buffer.CopyTo(buffer2); + Assert.True(buffer2.Length == 3); + } + #if NET [Fact] public void TestTryGetDataUnsafe() diff --git a/src/cswinrt/strings/additions/Windows.Storage.Streams/WindowsRuntimeBufferExtensions.cs b/src/cswinrt/strings/additions/Windows.Storage.Streams/WindowsRuntimeBufferExtensions.cs index 9b0ac48d3..defb5ff75 100644 --- a/src/cswinrt/strings/additions/Windows.Storage.Streams/WindowsRuntimeBufferExtensions.cs +++ b/src/cswinrt/strings/additions/Windows.Storage.Streams/WindowsRuntimeBufferExtensions.cs @@ -196,7 +196,7 @@ public static void CopyTo(this IBuffer source, uint sourceIndex, Span dest Debug.Assert(sourceIndex <= int.MaxValue); - Span srcSpan = source.TryGetUnderlyingData(out byte[] srcDataArr, out int srcOffset) ? srcDataArr.AsSpan(srcOffset + (int)sourceIndex, count) : source.GetSpanForCapacityUnsafe(sourceIndex); + Span srcSpan = source.TryGetUnderlyingData(out byte[] srcDataArr, out int srcOffset) ? srcDataArr.AsSpan(srcOffset + (int)sourceIndex, count) : source.GetSpanForCapacityUnsafe(sourceIndex).Slice(0, (int)count); srcSpan.CopyTo(destination); // Ensure source and destination stay alive for the copy operation @@ -252,8 +252,8 @@ public static void CopyTo(this IBuffer source, uint sourceIndex, IBuffer destina Debug.Assert(destinationIndex <= int.MaxValue); // If source are destination are backed by managed arrays, use the arrays instead of the pointers as it does not require pinning: - Span srcSpan = source.TryGetUnderlyingData(out byte[] srcDataArr, out int srcOffset) ? srcDataArr.AsSpan(srcOffset + (int)sourceIndex, (int)count) : source.GetSpanForCapacityUnsafe(sourceIndex); - Span destSpan = destination.TryGetUnderlyingData(out byte[] destDataArr, out int destOffset) ? destDataArr.AsSpan(destOffset + (int)destinationIndex) : destination.GetSpanForCapacityUnsafe(destinationIndex); + Span srcSpan = source.TryGetUnderlyingData(out byte[] srcDataArr, out int srcOffset) ? srcDataArr.AsSpan(srcOffset + (int)sourceIndex, (int)count) : source.GetSpanForCapacityUnsafe(sourceIndex).Slice(0, (int)count); + Span destSpan = destination.TryGetUnderlyingData(out byte[] destDataArr, out int destOffset) ? destDataArr.AsSpan(destOffset + (int)destinationIndex) : destination.GetSpanForCapacityUnsafe(destinationIndex).Slice(0, (int)count); srcSpan.CopyTo(destSpan);