Browse Source

Merge pull request #2780 from KirillAldashkin/main

Fix #2779 buffer overrun
pull/2786/head
James Jackson-South 2 years ago
committed by GitHub
parent
commit
57ecebfd8a
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 9
      src/ImageSharp/Image.WrapMemory.cs
  2. 33
      tests/ImageSharp.Tests/Image/ImageTests.WrapMemory.cs

9
src/ImageSharp/Image.WrapMemory.cs

@ -50,7 +50,7 @@ public abstract partial class Image
{ {
Guard.NotNull(configuration, nameof(configuration)); Guard.NotNull(configuration, nameof(configuration));
Guard.NotNull(metadata, nameof(metadata)); Guard.NotNull(metadata, nameof(metadata));
Guard.IsTrue(pixelMemory.Length >= width * height, nameof(pixelMemory), "The length of the input memory is less than the specified image size"); Guard.IsTrue(pixelMemory.Length >= (long)width * height, nameof(pixelMemory), "The length of the input memory is less than the specified image size");
MemoryGroup<TPixel> memorySource = MemoryGroup<TPixel>.Wrap(pixelMemory); MemoryGroup<TPixel> memorySource = MemoryGroup<TPixel>.Wrap(pixelMemory);
return new Image<TPixel>(configuration, memorySource, width, height, metadata); return new Image<TPixel>(configuration, memorySource, width, height, metadata);
@ -145,7 +145,7 @@ public abstract partial class Image
{ {
Guard.NotNull(configuration, nameof(configuration)); Guard.NotNull(configuration, nameof(configuration));
Guard.NotNull(metadata, nameof(metadata)); Guard.NotNull(metadata, nameof(metadata));
Guard.IsTrue(pixelMemoryOwner.Memory.Length >= width * height, nameof(pixelMemoryOwner), "The length of the input memory is less than the specified image size"); Guard.IsTrue(pixelMemoryOwner.Memory.Length >= (long)width * height, nameof(pixelMemoryOwner), "The length of the input memory is less than the specified image size");
MemoryGroup<TPixel> memorySource = MemoryGroup<TPixel>.Wrap(pixelMemoryOwner); MemoryGroup<TPixel> memorySource = MemoryGroup<TPixel>.Wrap(pixelMemoryOwner);
return new Image<TPixel>(configuration, memorySource, width, height, metadata); return new Image<TPixel>(configuration, memorySource, width, height, metadata);
@ -232,7 +232,7 @@ public abstract partial class Image
ByteMemoryManager<TPixel> memoryManager = new(byteMemory); ByteMemoryManager<TPixel> memoryManager = new(byteMemory);
Guard.IsTrue(memoryManager.Memory.Length >= width * height, nameof(byteMemory), "The length of the input memory is less than the specified image size"); Guard.IsTrue(memoryManager.Memory.Length >= (long)width * height, nameof(byteMemory), "The length of the input memory is less than the specified image size");
MemoryGroup<TPixel> memorySource = MemoryGroup<TPixel>.Wrap(memoryManager.Memory); MemoryGroup<TPixel> memorySource = MemoryGroup<TPixel>.Wrap(memoryManager.Memory);
return new Image<TPixel>(configuration, memorySource, width, height, metadata); return new Image<TPixel>(configuration, memorySource, width, height, metadata);
@ -422,10 +422,11 @@ public abstract partial class Image
Guard.IsFalse(pointer == null, nameof(pointer), "Pointer must be not null"); Guard.IsFalse(pointer == null, nameof(pointer), "Pointer must be not null");
Guard.NotNull(configuration, nameof(configuration)); Guard.NotNull(configuration, nameof(configuration));
Guard.NotNull(metadata, nameof(metadata)); Guard.NotNull(metadata, nameof(metadata));
Guard.MustBeLessThanOrEqualTo(height * (long)width, int.MaxValue, "Total amount of pixels exceeds int.MaxValue");
UnmanagedMemoryManager<TPixel> memoryManager = new(pointer, width * height); UnmanagedMemoryManager<TPixel> memoryManager = new(pointer, width * height);
Guard.MustBeGreaterThanOrEqualTo(bufferSizeInBytes, memoryManager.Memory.Span.Length, nameof(bufferSizeInBytes)); Guard.MustBeGreaterThanOrEqualTo(bufferSizeInBytes / sizeof(TPixel), memoryManager.Memory.Span.Length, nameof(bufferSizeInBytes));
MemoryGroup<TPixel> memorySource = MemoryGroup<TPixel>.Wrap(memoryManager.Memory); MemoryGroup<TPixel> memorySource = MemoryGroup<TPixel>.Wrap(memoryManager.Memory);
return new Image<TPixel>(configuration, memorySource, width, height, metadata); return new Image<TPixel>(configuration, memorySource, width, height, metadata);

33
tests/ImageSharp.Tests/Image/ImageTests.WrapMemory.cs

@ -294,19 +294,22 @@ public partial class ImageTests
} }
} }
[Fact] [Theory]
public unsafe void WrapMemory_Throws_OnTooLessWrongSize() [InlineData(20, 5, 5)]
[InlineData(1023, 32, 32)]
[InlineData(65536, 65537, 65536)]
public unsafe void WrapMemory_Throws_OnTooLessWrongSize(int size, int width, int height)
{ {
var cfg = Configuration.CreateDefaultInstance(); var cfg = Configuration.CreateDefaultInstance();
var metaData = new ImageMetadata(); var metaData = new ImageMetadata();
var array = new Rgba32[25]; var array = new Rgba32[size];
Exception thrownException = null; Exception thrownException = null;
fixed (void* ptr = array) fixed (void* ptr = array)
{ {
try try
{ {
using var image = Image.WrapMemory<Rgba32>(cfg, ptr, 24, 5, 5, metaData); using var image = Image.WrapMemory<Rgba32>(cfg, ptr, size * sizeof(Rgba32), width, height, metaData);
} }
catch (Exception e) catch (Exception e)
{ {
@ -317,24 +320,30 @@ public partial class ImageTests
Assert.IsType<ArgumentOutOfRangeException>(thrownException); Assert.IsType<ArgumentOutOfRangeException>(thrownException);
} }
[Fact] [Theory]
public unsafe void WrapMemory_FromPointer_CreatedImageIsCorrect() [InlineData(25, 5, 5)]
[InlineData(26, 5, 5)]
[InlineData(2, 1, 1)]
[InlineData(1024, 32, 32)]
[InlineData(2048, 32, 32)]
public unsafe void WrapMemory_FromPointer_CreatedImageIsCorrect(int size, int width, int height)
{ {
var cfg = Configuration.CreateDefaultInstance(); var cfg = Configuration.CreateDefaultInstance();
var metaData = new ImageMetadata(); var metaData = new ImageMetadata();
var array = new Rgba32[25]; var array = new Rgba32[size];
fixed (void* ptr = array) fixed (void* ptr = array)
{ {
using (var image = Image.WrapMemory<Rgba32>(cfg, ptr, 25, 5, 5, metaData)) using (var image = Image.WrapMemory<Rgba32>(cfg, ptr, size * sizeof(Rgba32), width, height, metaData))
{ {
Assert.True(image.DangerousTryGetSinglePixelMemory(out Memory<Rgba32> imageMem)); Assert.True(image.DangerousTryGetSinglePixelMemory(out Memory<Rgba32> imageMem));
Span<Rgba32> imageSpan = imageMem.Span; Span<Rgba32> imageSpan = imageMem.Span;
Span<Rgba32> sourceSpan = array.AsSpan(0, width * height);
ref Rgba32 pixel0 = ref imageSpan[0]; ref Rgba32 pixel0 = ref imageSpan[0];
Assert.True(Unsafe.AreSame(ref array[0], ref pixel0)); Assert.True(Unsafe.AreSame(ref sourceSpan[0], ref pixel0));
ref Rgba32 pixel_1 = ref imageSpan[imageSpan.Length - 1]; ref Rgba32 pixel_1 = ref imageSpan[imageSpan.Length - 1];
Assert.True(Unsafe.AreSame(ref array[array.Length - 1], ref pixel_1)); Assert.True(Unsafe.AreSame(ref sourceSpan[sourceSpan.Length - 1], ref pixel_1));
Assert.Equal(cfg, image.Configuration); Assert.Equal(cfg, image.Configuration);
Assert.Equal(metaData, image.Metadata); Assert.Equal(metaData, image.Metadata);
@ -395,6 +404,7 @@ public partial class ImageTests
[InlineData(0, 5, 5)] [InlineData(0, 5, 5)]
[InlineData(20, 5, 5)] [InlineData(20, 5, 5)]
[InlineData(1023, 32, 32)] [InlineData(1023, 32, 32)]
[InlineData(65536, 65537, 65536)]
public void WrapMemory_MemoryOfT_InvalidSize(int size, int height, int width) public void WrapMemory_MemoryOfT_InvalidSize(int size, int height, int width)
{ {
var array = new Rgba32[size]; var array = new Rgba32[size];
@ -430,6 +440,7 @@ public partial class ImageTests
[InlineData(0, 5, 5)] [InlineData(0, 5, 5)]
[InlineData(20, 5, 5)] [InlineData(20, 5, 5)]
[InlineData(1023, 32, 32)] [InlineData(1023, 32, 32)]
[InlineData(65536, 65537, 65536)]
public void WrapMemory_IMemoryOwnerOfT_InvalidSize(int size, int height, int width) public void WrapMemory_IMemoryOwnerOfT_InvalidSize(int size, int height, int width)
{ {
var array = new Rgba32[size]; var array = new Rgba32[size];
@ -476,6 +487,7 @@ public partial class ImageTests
[InlineData(0, 5, 5)] [InlineData(0, 5, 5)]
[InlineData(20, 5, 5)] [InlineData(20, 5, 5)]
[InlineData(1023, 32, 32)] [InlineData(1023, 32, 32)]
[InlineData(65536, 65537, 65536)]
public void WrapMemory_IMemoryOwnerOfByte_InvalidSize(int size, int height, int width) public void WrapMemory_IMemoryOwnerOfByte_InvalidSize(int size, int height, int width)
{ {
var array = new byte[size * Unsafe.SizeOf<Rgba32>()]; var array = new byte[size * Unsafe.SizeOf<Rgba32>()];
@ -523,6 +535,7 @@ public partial class ImageTests
[InlineData(0, 5, 5)] [InlineData(0, 5, 5)]
[InlineData(20, 5, 5)] [InlineData(20, 5, 5)]
[InlineData(1023, 32, 32)] [InlineData(1023, 32, 32)]
[InlineData(65536, 65537, 65536)]
public void WrapMemory_MemoryOfByte_InvalidSize(int size, int height, int width) public void WrapMemory_MemoryOfByte_InvalidSize(int size, int height, int width)
{ {
var array = new byte[size * Unsafe.SizeOf<Rgba32>()]; var array = new byte[size * Unsafe.SizeOf<Rgba32>()];

Loading…
Cancel
Save