diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs index 19e8b62fe..b24a5eabd 100644 --- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs @@ -1159,6 +1159,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// /// Reads the cycle redundancy chunk from the data. /// + [MethodImpl(InliningOptions.ShortMethod)] private uint ReadChunkCrc() { uint crc = 0; @@ -1174,6 +1175,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// Skips the chunk data and the cycle redundancy chunk read from the data. /// /// The image format chunk. + [MethodImpl(InliningOptions.ShortMethod)] private void SkipChunkDataAndCrc(in PngChunk chunk) { this.currentStream.Skip(chunk.Length); @@ -1184,6 +1186,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// Reads the chunk data from the stream. /// /// The length of the chunk data to read. + [MethodImpl(InliningOptions.ShortMethod)] private IManagedByteBuffer ReadChunkData(int length) { // We rent the buffer here to return it afterwards in Decode() @@ -1200,6 +1203,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// /// Thrown if the input stream is not valid. /// + [MethodImpl(InliningOptions.ShortMethod)] private PngChunkType ReadChunkType() { if (this.currentStream.Read(this.buffer, 0, 4) == 4) @@ -1221,6 +1225,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// /// Whether the length was read. /// + [MethodImpl(InliningOptions.ShortMethod)] private bool TryReadChunkLength(out int result) { if (this.currentStream.Read(this.buffer, 0, 4) == 4) diff --git a/src/ImageSharp/Formats/Png/PngThrowHelper.cs b/src/ImageSharp/Formats/Png/PngThrowHelper.cs index bc6093948..00b40c50b 100644 --- a/src/ImageSharp/Formats/Png/PngThrowHelper.cs +++ b/src/ImageSharp/Formats/Png/PngThrowHelper.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System; +using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; namespace SixLabors.ImageSharp.Formats.Png @@ -17,13 +18,16 @@ namespace SixLabors.ImageSharp.Formats.Png [MethodImpl(InliningOptions.ColdPath)] public static void ThrowNoData() => throw new ImageFormatException("PNG Image does not contain a data chunk"); + [MethodImpl(InliningOptions.ColdPath)] public static void ThrowInvalidChunkType() => throw new ImageFormatException("Invalid PNG data."); [MethodImpl(InliningOptions.ColdPath)] public static void ThrowInvalidChunkCrc(string chunkTypeName) => throw new ImageFormatException($"CRC Error. PNG {chunkTypeName} chunk is corrupt!"); + [MethodImpl(InliningOptions.ColdPath)] public static void ThrowNotSupportedColor() => new NotSupportedException("Unsupported PNG color type"); + [MethodImpl(InliningOptions.ColdPath)] public static void ThrowUnknownFilter() => throw new ImageFormatException("Unknown filter type."); } } diff --git a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.Chunks.cs b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.Chunks.cs index e976d5a76..660d5b724 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.Chunks.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.Chunks.cs @@ -54,7 +54,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png [InlineData((uint)PngChunkType.Header)] // IHDR [InlineData((uint)PngChunkType.Palette)] // PLTE // [InlineData(PngChunkTypes.Data)] //TODO: Figure out how to test this - [InlineData((uint)PngChunkType.End)] // IEND public void Decode_IncorrectCRCForCriticalChunk_ExceptionIsThrown(uint chunkType) { string chunkName = GetChunkTypeName(chunkType); @@ -74,26 +73,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png } } - [Theory] - [InlineData((uint)PngChunkType.Gamma)] // gAMA - [InlineData((uint)PngChunkType.Transparency)] // tRNS - [InlineData((uint)PngChunkType.Physical)] // pHYs: It's ok to test physical as we don't throw for duplicate chunks. - //[InlineData(PngChunkTypes.Text)] //TODO: Figure out how to test this - public void Decode_IncorrectCRCForNonCriticalChunk_ExceptionIsThrown(uint chunkType) - { - string chunkName = GetChunkTypeName(chunkType); - - using (var memStream = new MemoryStream()) - { - WriteHeaderChunk(memStream); - WriteChunk(memStream, chunkName); - WriteDataChunk(memStream); - - var decoder = new PngDecoder(); - decoder.Decode(null, memStream); - } - } - private static string GetChunkTypeName(uint value) { var data = new byte[4]; diff --git a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs index e064c0fb0..1acb4fe2d 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs @@ -4,11 +4,11 @@ // ReSharper disable InconsistentNaming using System.IO; - +using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Formats.Png; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; - +using SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs; using Xunit; namespace SixLabors.ImageSharp.Tests.Formats.Png @@ -42,6 +42,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png TestImages.Png.Bad.ZlibOverflow, TestImages.Png.Bad.ZlibOverflow2, TestImages.Png.Bad.ZlibZtxtBadHeader, + TestImages.Png.Bad.Issue1047_BadEndChunk }; public static readonly string[] TestImages48Bpp = @@ -90,7 +91,15 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png using (Image image = provider.GetImage(new PngDecoder())) { image.DebugSave(provider); - image.CompareToOriginal(provider, ImageComparer.Exact); + + if (provider.Utility.SourceFileOrDescription == TestImages.Png.Bad.Issue1047_BadEndChunk) + { + image.CompareToOriginal(provider, ImageComparer.Exact, (IImageDecoder)SystemDrawingReferenceDecoder.Instance); + } + else + { + image.CompareToOriginal(provider, ImageComparer.Exact); + } } } diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index 177749869..d19dbe834 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -99,6 +99,7 @@ namespace SixLabors.ImageSharp.Tests public const string ZlibOverflow = "Png/zlib-overflow.png"; public const string ZlibOverflow2 = "Png/zlib-overflow2.png"; public const string ZlibZtxtBadHeader = "Png/zlib-ztxt-bad-header.png"; + public const string Issue1047_BadEndChunk = "Png/issues/Issue_1047.png"; } public static readonly string[] All = diff --git a/tests/Images/Input/Png/issues/Issue_1047.png b/tests/Images/Input/Png/issues/Issue_1047.png new file mode 100644 index 000000000..0f85dc53c Binary files /dev/null and b/tests/Images/Input/Png/issues/Issue_1047.png differ