diff --git a/src/ImageSharp/Image.WrapMemory.cs b/src/ImageSharp/Image.WrapMemory.cs index 0c9e14896..d8cea246f 100644 --- a/src/ImageSharp/Image.WrapMemory.cs +++ b/src/ImageSharp/Image.WrapMemory.cs @@ -403,6 +403,7 @@ public abstract partial class Image /// The pixel type /// The /// The pointer to the target memory buffer to wrap. + /// The byte length of the memory allocated. /// The width of the memory image. /// The height of the memory image. /// The . @@ -412,6 +413,7 @@ public abstract partial class Image public static unsafe Image WrapMemory( Configuration configuration, void* pointer, + int bufferSizeInBytes, int width, int height, ImageMetadata metadata) @@ -423,6 +425,8 @@ public abstract partial class Image UnmanagedMemoryManager memoryManager = new(pointer, width * height); + Guard.MustBeGreaterThanOrEqualTo(bufferSizeInBytes, memoryManager.Memory.Span.Length, nameof(bufferSizeInBytes)); + MemoryGroup memorySource = MemoryGroup.Wrap(memoryManager.Memory); return new Image(configuration, memorySource, width, height, metadata); } @@ -453,6 +457,7 @@ public abstract partial class Image /// The pixel type /// The /// The pointer to the target memory buffer to wrap. + /// The byte length of the memory allocated. /// The width of the memory image. /// The height of the memory image. /// The configuration is null. @@ -460,10 +465,11 @@ public abstract partial class Image public static unsafe Image WrapMemory( Configuration configuration, void* pointer, + int bufferSizeInBytes, int width, int height) where TPixel : unmanaged, IPixel - => WrapMemory(configuration, pointer, width, height, new ImageMetadata()); + => WrapMemory(configuration, pointer, bufferSizeInBytes, width, height, new ImageMetadata()); /// /// @@ -490,13 +496,15 @@ public abstract partial class Image /// /// The pixel type. /// The pointer to the target memory buffer to wrap. + /// The byte length of the memory allocated. /// The width of the memory image. /// The height of the memory image. /// An instance. public static unsafe Image WrapMemory( void* pointer, + int bufferSizeInBytes, int width, int height) where TPixel : unmanaged, IPixel - => WrapMemory(Configuration.Default, pointer, width, height); + => WrapMemory(Configuration.Default, pointer, bufferSizeInBytes, width, height); } diff --git a/tests/ImageSharp.Tests/Image/ImageTests.WrapMemory.cs b/tests/ImageSharp.Tests/Image/ImageTests.WrapMemory.cs index 1b2c20548..b62f3ebd8 100644 --- a/tests/ImageSharp.Tests/Image/ImageTests.WrapMemory.cs +++ b/tests/ImageSharp.Tests/Image/ImageTests.WrapMemory.cs @@ -108,7 +108,8 @@ public partial class ImageTests if (remainder != 0) { - ThrowHelper.ThrowArgumentException("The input index doesn't result in an aligned item access", nameof(elementIndex)); + ThrowHelper.ThrowArgumentException("The input index doesn't result in an aligned item access", + nameof(elementIndex)); } return this.memory.Slice(shiftedOffset).Pin(); @@ -269,7 +270,8 @@ public partial class ImageTests // To check that the underlying data matches, we can just manually check their lenth, and the // fact that a reference to the first pixel in both spans is actually the same memory location. Assert.Equal(pixelSpan.Length, imageSpan.Length); - Assert.True(Unsafe.AreSame(ref pixelSpan.GetPinnableReference(), ref imageSpan.GetPinnableReference())); + Assert.True(Unsafe.AreSame(ref pixelSpan.GetPinnableReference(), + ref imageSpan.GetPinnableReference())); image.GetPixelMemoryGroup().Fill(bg); image.ProcessPixelRows(accessor => @@ -292,6 +294,30 @@ public partial class ImageTests } } + + [Fact] + public unsafe void WrapMemory_Throws_OnTooLessWrongSize() + { + var cfg = Configuration.CreateDefaultInstance(); + var metaData = new ImageMetadata(); + + var array = new Rgba32[25]; + Exception thrownException = null; + fixed (void* ptr = array) + { + try + { + using (var image = Image.WrapMemory(cfg, ptr, 24, 5, 5, metaData)); + } + catch (Exception e) + { + thrownException = e; + } + } + + Assert.IsType(thrownException); + } + [Fact] public unsafe void WrapMemory_FromPointer_CreatedImageIsCorrect() { @@ -302,7 +328,7 @@ public partial class ImageTests fixed (void* ptr = array) { - using (var image = Image.WrapMemory(cfg, ptr, 5, 5, metaData)) + using (var image = Image.WrapMemory(cfg, ptr, 25, 5, 5, metaData)) { Assert.True(image.DangerousTryGetSinglePixelMemory(out Memory imageMem)); Span imageSpan = imageMem.Span; @@ -335,13 +361,14 @@ public partial class ImageTests fixed (void* p = pixelMemory.Span) { - using (var image = Image.WrapMemory(p, bmp.Width, bmp.Height)) + using (var image = Image.WrapMemory(p, pixelMemory.Length, bmp.Width, bmp.Height)) { Span pixelSpan = pixelMemory.Span; Span imageSpan = image.GetRootFramePixelBuffer().DangerousGetSingleMemory().Span; Assert.Equal(pixelSpan.Length, imageSpan.Length); - Assert.True(Unsafe.AreSame(ref pixelSpan.GetPinnableReference(), ref imageSpan.GetPinnableReference())); + Assert.True(Unsafe.AreSame(ref pixelSpan.GetPinnableReference(), + ref imageSpan.GetPinnableReference())); image.GetPixelMemoryGroup().Fill(bg); image.ProcessPixelRows(accessor => @@ -527,10 +554,11 @@ public partial class ImageTests [InlineData(1023, 32, 32)] public unsafe void WrapMemory_Pointer_Null(int size, int height, int width) { - Assert.Throws(() => Image.WrapMemory((void*)null, height, width)); + Assert.Throws(() => Image.WrapMemory((void*)null, size, height, width)); } private static bool ShouldSkipBitmapTest => - !TestEnvironment.Is64BitProcess || (TestHelpers.ImageSharpBuiltAgainst != "netcoreapp3.1" && TestHelpers.ImageSharpBuiltAgainst != "netcoreapp2.1"); + !TestEnvironment.Is64BitProcess || (TestHelpers.ImageSharpBuiltAgainst != "netcoreapp3.1" && + TestHelpers.ImageSharpBuiltAgainst != "netcoreapp2.1"); } }