diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
index 960c2ecd22..fdd371f547 100644
--- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
+++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
@@ -114,6 +114,9 @@ namespace SixLabors.ImageSharp.Formats.Bmp
this.options = options;
}
+ ///
+ /// Gets the dimensions of the image.
+ ///
public Size Dimensions => new Size(this.infoHeader.Width, this.infoHeader.Height);
///
diff --git a/src/ImageSharp/Formats/Gif/GifDecoder.cs b/src/ImageSharp/Formats/Gif/GifDecoder.cs
index 7691ec1aa5..24e3d88261 100644
--- a/src/ImageSharp/Formats/Gif/GifDecoder.cs
+++ b/src/ImageSharp/Formats/Gif/GifDecoder.cs
@@ -1,7 +1,9 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
+using System;
using System.IO;
+using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.Metadata;
using SixLabors.ImageSharp.PixelFormats;
@@ -27,7 +29,19 @@ namespace SixLabors.ImageSharp.Formats.Gif
where TPixel : struct, IPixel
{
var decoder = new GifDecoderCore(configuration, this);
- return decoder.Decode(stream);
+
+ try
+ {
+ return decoder.Decode(stream);
+ }
+ catch (InvalidMemoryOperationException ex)
+ {
+ Size dims = decoder.Dimensions;
+
+ // TODO: use InvalidImageContentException here, if we decide to define it
+ // https://github.com/SixLabors/ImageSharp/issues/1110
+ throw new ImageFormatException($"Can not decode image. Failed to allocate buffers for possibly degenerate dimensions: {dims.Width}x{dims.Height}.", ex);
+ }
}
///
diff --git a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs
index 98dbddb481..bc508cba74 100644
--- a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs
+++ b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs
@@ -86,10 +86,15 @@ namespace SixLabors.ImageSharp.Formats.Gif
public bool IgnoreMetadata { get; internal set; }
///
- /// Gets the decoding mode for multi-frame images
+ /// Gets the decoding mode for multi-frame images.
///
public FrameDecodingMode DecodingMode { get; }
+ ///
+ /// Gets the dimensions of the image.
+ ///
+ public Size Dimensions => new Size(this.imageDescriptor.Width, this.imageDescriptor.Height);
+
private MemoryAllocator MemoryAllocator => this.configuration.MemoryAllocator;
///
diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs
index ff75e4290f..2701bd2a74 100644
--- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs
+++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs
@@ -132,6 +132,9 @@ namespace SixLabors.ImageSharp.Formats.Png
this.ignoreMetadata = options.IgnoreMetadata;
}
+ ///
+ /// Gets the dimensions of the image.
+ ///
public Size Dimensions => new Size(this.header.Width, this.header.Height);
///
diff --git a/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs b/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs
index 1717df63b6..6768f4db30 100644
--- a/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs
+++ b/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs
@@ -61,6 +61,9 @@ namespace SixLabors.ImageSharp.Formats.Tga
this.options = options;
}
+ ///
+ /// Gets the dimensions of the image.
+ ///
public Size Dimensions => new Size(this.fileHeader.Width, this.fileHeader.Height);
///
diff --git a/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs
index 99dc2d06da..ea244f68ab 100644
--- a/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs
+++ b/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs
@@ -4,10 +4,14 @@
using System;
using System.Collections.Generic;
using System.IO;
+using Microsoft.DotNet.RemoteExecutor;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Formats.Gif;
+using SixLabors.ImageSharp.Formats.Tga;
+using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.Metadata;
using SixLabors.ImageSharp.PixelFormats;
+using SixLabors.ImageSharp.Tests.TestUtilities;
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison;
using Xunit;
@@ -163,5 +167,41 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif
}
}
}
+
+ [Theory]
+ [WithFile(TestImages.Gif.Giphy, PixelTypes.Rgba32)]
+ [WithFile(TestImages.Gif.Kumin, PixelTypes.Rgba32)]
+ public void GifDecoder_DegenerateMemoryRequest_ShouldTranslateTo_ImageFormatException(TestImageProvider provider)
+ where TPixel : struct, IPixel
+ {
+ provider.LimitAllocatorBufferCapacity().InPixels(10);
+ ImageFormatException ex = Assert.Throws(provider.GetImage);
+ Assert.IsType(ex.InnerException);
+ }
+
+ [Theory]
+ [WithFile(TestImages.Gif.Giphy, PixelTypes.Rgba32)]
+ [WithFile(TestImages.Gif.Kumin, PixelTypes.Rgba32)]
+ public void GifDecoder_CanDecode_WithLimitedAllocatorBufferCapacity(TestImageProvider provider)
+ where TPixel : struct, IPixel
+ {
+ static void RunTest(string providerDump, string nonContiguousBuffersStr)
+ {
+ TestImageProvider provider = BasicSerializer.Deserialize>(providerDump);
+
+ provider.LimitAllocatorBufferCapacity().InPixels(100);
+
+ using Image image = provider.GetImage(new GifDecoder());
+ image.DebugSave(provider);
+ image.CompareToOriginal(provider);
+ }
+
+ string providerDump = BasicSerializer.Serialize(provider);
+ RemoteExecutor.Invoke(
+ RunTest,
+ providerDump,
+ "Disco")
+ .Dispose();
+ }
}
}
diff --git a/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs
index fe1faa5aed..4c710cdb2e 100644
--- a/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs
+++ b/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs
@@ -26,10 +26,16 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif
};
[Theory]
- [WithTestPatternImages(100, 100, TestPixelTypes)]
- public void EncodeGeneratedPatterns(TestImageProvider provider)
+ [WithTestPatternImages(100, 100, TestPixelTypes, false)]
+ [WithTestPatternImages(100, 100, TestPixelTypes, false)]
+ public void EncodeGeneratedPatterns(TestImageProvider provider, bool limitAllocationBuffer)
where TPixel : struct, IPixel
{
+ if (limitAllocationBuffer)
+ {
+ provider.LimitAllocatorBufferCapacity().InPixels(100);
+ }
+
using (Image image = provider.GetImage())
{
var encoder = new GifEncoder