diff --git a/src/ImageSharp/Image.FromBytes.cs b/src/ImageSharp/Image.FromBytes.cs index 96ef84510f..d48065d019 100644 --- a/src/ImageSharp/Image.FromBytes.cs +++ b/src/ImageSharp/Image.FromBytes.cs @@ -34,7 +34,12 @@ public abstract partial class Image /// The encoded image format is unknown. public static unsafe IImageFormat DetectFormat(DecoderOptions options, ReadOnlySpan buffer) { - Guard.NotNull(options, nameof(options.Configuration)); + Guard.NotNull(options, nameof(options)); + + if (buffer.IsEmpty) + { + throw new UnknownImageFormatException("Cannot detect image format from empty data."); + } fixed (byte* ptr = buffer) { @@ -66,6 +71,13 @@ public abstract partial class Image /// The encoded image format is unknown. public static unsafe ImageInfo Identify(DecoderOptions options, ReadOnlySpan buffer) { + Guard.NotNull(options, nameof(options)); + + if (buffer.IsEmpty) + { + throw new UnknownImageFormatException("Cannot identify image format from empty data."); + } + fixed (byte* ptr = buffer) { using UnmanagedMemoryStream stream = new(ptr, buffer.Length); @@ -99,6 +111,13 @@ public abstract partial class Image /// The encoded image format is unknown. public static unsafe Image Load(DecoderOptions options, ReadOnlySpan buffer) { + Guard.NotNull(options, nameof(options)); + + if (buffer.IsEmpty) + { + throw new UnknownImageFormatException("Cannot load image from empty data."); + } + fixed (byte* ptr = buffer) { using UnmanagedMemoryStream stream = new(ptr, buffer.Length); @@ -133,6 +152,13 @@ public abstract partial class Image public static unsafe Image Load(DecoderOptions options, ReadOnlySpan data) where TPixel : unmanaged, IPixel { + Guard.NotNull(options, nameof(options)); + + if (data.IsEmpty) + { + throw new UnknownImageFormatException("Cannot load image from empty data."); + } + fixed (byte* ptr = data) { using UnmanagedMemoryStream stream = new(ptr, data.Length); diff --git a/src/ImageSharp/Image.LoadPixelData.cs b/src/ImageSharp/Image.LoadPixelData.cs index 53b672b7dd..efe1b6e2fb 100644 --- a/src/ImageSharp/Image.LoadPixelData.cs +++ b/src/ImageSharp/Image.LoadPixelData.cs @@ -69,6 +69,11 @@ public abstract partial class Image { Guard.NotNull(configuration, nameof(configuration)); + if (data.IsEmpty) + { + throw new ArgumentException("Pixel data cannot be empty.", nameof(data)); + } + int count = width * height; Guard.MustBeGreaterThanOrEqualTo(data.Length, count, nameof(data)); diff --git a/tests/ImageSharp.Tests/Image/ImageTests.DetectFormat.cs b/tests/ImageSharp.Tests/Image/ImageTests.DetectFormat.cs index a1966e2bb0..178f5375f1 100644 --- a/tests/ImageSharp.Tests/Image/ImageTests.DetectFormat.cs +++ b/tests/ImageSharp.Tests/Image/ImageTests.DetectFormat.cs @@ -50,6 +50,10 @@ public partial class ImageTests Assert.Equal(this.LocalImageFormat, format); } + [Fact] + public void FromBytes_EmptySpan_Throws() + => Assert.Throws(() => Image.DetectFormat([])); + [Fact] public void FromFileSystemPath_GlobalConfiguration() { diff --git a/tests/ImageSharp.Tests/Image/ImageTests.Identify.cs b/tests/ImageSharp.Tests/Image/ImageTests.Identify.cs index 490fa3b0b0..433a1e1018 100644 --- a/tests/ImageSharp.Tests/Image/ImageTests.Identify.cs +++ b/tests/ImageSharp.Tests/Image/ImageTests.Identify.cs @@ -38,6 +38,10 @@ public partial class ImageTests Assert.Equal(ExpectedGlobalFormat, info.Metadata.DecodedImageFormat); } + [Fact] + public void FromBytes_EmptySpan_Throws() + => Assert.Throws(() => Image.Identify([])); + [Fact] public void FromBytes_CustomConfiguration() { diff --git a/tests/ImageSharp.Tests/Image/ImageTests.Load_FromBytes_PassLocalConfiguration.cs b/tests/ImageSharp.Tests/Image/ImageTests.Load_FromBytes_PassLocalConfiguration.cs index 3a47a0ea73..600bed0102 100644 --- a/tests/ImageSharp.Tests/Image/ImageTests.Load_FromBytes_PassLocalConfiguration.cs +++ b/tests/ImageSharp.Tests/Image/ImageTests.Load_FromBytes_PassLocalConfiguration.cs @@ -79,5 +79,16 @@ public partial class ImageTests this.TestFormat.VerifyAgnosticDecodeCall(this.Marker, this.TopLevelConfiguration); } + + [Fact] + public void FromBytes_EmptySpan_Throws() + { + DecoderOptions options = new() + { + Configuration = this.TopLevelConfiguration + }; + + Assert.Throws(() => Image.Load(options, [])); + } } } diff --git a/tests/ImageSharp.Tests/Image/ImageTests.Load_FromBytes_UseGlobalConfiguration.cs b/tests/ImageSharp.Tests/Image/ImageTests.Load_FromBytes_UseGlobalConfiguration.cs index 00ec985ac2..a0ce1e5d86 100644 --- a/tests/ImageSharp.Tests/Image/ImageTests.Load_FromBytes_UseGlobalConfiguration.cs +++ b/tests/ImageSharp.Tests/Image/ImageTests.Load_FromBytes_UseGlobalConfiguration.cs @@ -45,5 +45,9 @@ public partial class ImageTests VerifyDecodedImage(img); Assert.IsType(img.Metadata.DecodedImageFormat); } + + [Fact] + public void FromBytes_EmptySpan_Throws() + => Assert.ThrowsAny(() => Image.Load([])); } } diff --git a/tests/ImageSharp.Tests/Image/ImageTests.Load_FromStream_ThrowsRightException.cs b/tests/ImageSharp.Tests/Image/ImageTests.Load_FromStream_ThrowsRightException.cs index a064b64723..c2609545d3 100644 --- a/tests/ImageSharp.Tests/Image/ImageTests.Load_FromStream_ThrowsRightException.cs +++ b/tests/ImageSharp.Tests/Image/ImageTests.Load_FromStream_ThrowsRightException.cs @@ -32,6 +32,17 @@ public partial class ImageTests } }); - public void Dispose() => this.Stream?.Dispose(); + [Fact] + public void FromStream_Empty_Throws() + { + using MemoryStream ms = new(); + Assert.Throws(() => Image.Load(DecoderOptions.Default, ms)); + } + + public void Dispose() + { + this.Stream?.Dispose(); + GC.SuppressFinalize(this); + } } }