diff --git a/src/ImageSharp/Common/Exceptions/ImageFormatException.cs b/src/ImageSharp/Common/Exceptions/ImageFormatException.cs index 8b9dbe1b80..4028b70b0e 100644 --- a/src/ImageSharp/Common/Exceptions/ImageFormatException.cs +++ b/src/ImageSharp/Common/Exceptions/ImageFormatException.cs @@ -7,7 +7,7 @@ namespace SixLabors.ImageSharp { /// /// The exception that is thrown when the library tries to load - /// an image, which has an invalid format. + /// an image, which has format or content that is invalid or unsupported by ImageSharp. /// public class ImageFormatException : Exception { diff --git a/src/ImageSharp/Formats/IImageDecoder.cs b/src/ImageSharp/Formats/IImageDecoder.cs index e8e84de7d8..7188b57a6d 100644 --- a/src/ImageSharp/Formats/IImageDecoder.cs +++ b/src/ImageSharp/Formats/IImageDecoder.cs @@ -18,6 +18,7 @@ namespace SixLabors.ImageSharp.Formats /// The configuration for the image. /// The containing image data. /// The . + // TODO: Document ImageFormatExceptions (https://github.com/SixLabors/ImageSharp/issues/1110) Image Decode(Configuration configuration, Stream stream) where TPixel : struct, IPixel; @@ -27,6 +28,7 @@ namespace SixLabors.ImageSharp.Formats /// The configuration for the image. /// The containing image data. /// The . + // TODO: Document ImageFormatExceptions (https://github.com/SixLabors/ImageSharp/issues/1110) Image Decode(Configuration configuration, Stream stream); } } diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoder.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoder.cs index 4e1c0c1beb..187e432694 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegDecoder.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegDecoder.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System.IO; +using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Formats.Jpeg @@ -22,10 +23,19 @@ namespace SixLabors.ImageSharp.Formats.Jpeg { Guard.NotNull(stream, nameof(stream)); - using (var decoder = new JpegDecoderCore(configuration, this)) + using var decoder = new JpegDecoderCore(configuration, this); + try { return decoder.Decode(stream); } + catch (InvalidMemoryOperationException ex) + { + (int w, int h) = (decoder.ImageWidth, decoder.ImageHeight); + + // TODO: use InvalidImageContentException here, if we decide to define it + // https://github.com/SixLabors/ImageSharp/issues/1110 + throw new ImageFormatException($"Can not decode the image having degenerate dimensions of {w}x{h}.", ex); + } } /// diff --git a/src/ImageSharp/Memory/InvalidMemoryOperationException.cs b/src/ImageSharp/Memory/InvalidMemoryOperationException.cs index 51ed7e8616..c1d5c5d416 100644 --- a/src/ImageSharp/Memory/InvalidMemoryOperationException.cs +++ b/src/ImageSharp/Memory/InvalidMemoryOperationException.cs @@ -6,7 +6,8 @@ using System; namespace SixLabors.ImageSharp.Memory { /// - /// Exception thrown on invalid memory (allocation) requests. + /// Exception thrown when the library detects an invalid memory allocation request, + /// or an attempt has been made to use an invalidated . /// public class InvalidMemoryOperationException : InvalidOperationException { diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Baseline.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Baseline.cs index dc4a56195b..e237c65c68 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Baseline.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Baseline.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. using Microsoft.DotNet.RemoteExecutor; +using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Tests.TestUtilities; using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; @@ -48,7 +49,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg [Theory] [WithFileCollection(nameof(UnrecoverableTestJpegs), PixelTypes.Rgba32)] - public void UnrecoverableImagesShouldThrowCorrectError(TestImageProvider provider) + public void UnrecoverableImage_Throws_ImageFormatException(TestImageProvider provider) where TPixel : struct, IPixel => Assert.Throws(provider.GetImage); } } diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs index d829b5f980..1bf01fd511 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs @@ -105,6 +105,18 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg appendPixelTypeToFileName: false); } + [Theory] + [WithFile(TestImages.Jpeg.Baseline.Floorplan, PixelTypes.Rgba32)] + [WithFile(TestImages.Jpeg.Progressive.Festzug, PixelTypes.Rgba32)] + public void DegenerateMemoryRequest_ShouldTranslateTo_ImageFormatException(TestImageProvider provider) + where TPixel : struct, IPixel + { + provider.LimitAllocatorBufferCapacity(100); + ImageFormatException ex = Assert.Throws(provider.GetImage); + this.Output.WriteLine(ex.Message); + Assert.IsType(ex.InnerException); + } + // DEBUG ONLY! // The PDF.js output should be saved by "tests\ImageSharp.Tests\Formats\Jpg\pdfjs\jpeg-converter.htm" // into "\tests\Images\ActualOutput\JpegDecoderTests\"