diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs
index cdbd3a6893..95211c5f3d 100644
--- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs
+++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs
@@ -306,6 +306,15 @@ namespace ImageSharp.Formats
return result;
}
+ private static bool IsCriticalChunk(PngChunk chunk)
+ {
+ return
+ chunk.Type == PngChunkTypes.Header ||
+ chunk.Type == PngChunkTypes.Palette ||
+ chunk.Type == PngChunkTypes.Data ||
+ chunk.Type == PngChunkTypes.End;
+ }
+
///
/// Reads the data chunk containing physical dimension data.
///
@@ -1017,9 +1026,9 @@ namespace ImageSharp.Formats
this.crc.Update(this.chunkTypeBuffer);
this.crc.Update(chunk.Data, 0, chunk.Length);
- if (this.crc.Value != chunk.Crc)
+ if (this.crc.Value != chunk.Crc && IsCriticalChunk(chunk))
{
- throw new ImageFormatException("CRC Error. PNG Image chunk is corrupt!");
+ throw new ImageFormatException($"CRC Error. PNG {chunk.Type} chunk is corrupt!");
}
}
diff --git a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs
index ee8a2ee55b..3c335441ab 100644
--- a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs
+++ b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs
@@ -3,14 +3,15 @@
// Licensed under the Apache License, Version 2.0.
//
+using System.IO;
+using System.IO.Compression;
+using System.Text;
+using ImageSharp.Formats;
+using ImageSharp.PixelFormats;
+using Xunit;
+
namespace ImageSharp.Tests
{
- using System.Text;
- using Xunit;
-
- using ImageSharp.Formats;
- using ImageSharp.PixelFormats;
-
public class PngDecoderTests
{
private const PixelTypes PixelTypes = Tests.PixelTypes.Rgba32 | Tests.PixelTypes.RgbaVector | Tests.PixelTypes.Argb32;
@@ -35,12 +36,12 @@ namespace ImageSharp.Tests
[Fact]
public void Decode_IgnoreMetadataIsFalse_TextChunckIsRead()
{
- PngDecoder options = new PngDecoder()
+ var options = new PngDecoder()
{
IgnoreMetadata = false
};
- TestFile testFile = TestFile.Create(TestImages.Png.Blur);
+ var testFile = TestFile.Create(TestImages.Png.Blur);
using (Image image = testFile.CreateImage(options))
{
@@ -53,12 +54,12 @@ namespace ImageSharp.Tests
[Fact]
public void Decode_IgnoreMetadataIsTrue_TextChunksAreIgnored()
{
- PngDecoder options = new PngDecoder()
+ var options = new PngDecoder()
{
IgnoreMetadata = true
};
- TestFile testFile = TestFile.Create(TestImages.Png.Blur);
+ var testFile = TestFile.Create(TestImages.Png.Blur);
using (Image image = testFile.CreateImage(options))
{
@@ -69,12 +70,12 @@ namespace ImageSharp.Tests
[Fact]
public void Decode_TextEncodingSetToUnicode_TextIsReadWithCorrectEncoding()
{
- PngDecoder options = new PngDecoder()
+ var options = new PngDecoder()
{
TextEncoding = Encoding.Unicode
};
- TestFile testFile = TestFile.Create(TestImages.Png.Blur);
+ var testFile = TestFile.Create(TestImages.Png.Blur);
using (Image image = testFile.CreateImage(options))
{
@@ -82,5 +83,67 @@ namespace ImageSharp.Tests
Assert.Equal("潓瑦慷敲", image.MetaData.Properties[0].Name);
}
}
+
+ [Theory]
+ [InlineData(PngChunkTypes.Header)]
+ [InlineData(PngChunkTypes.Palette)]
+ // [InlineData(PngChunkTypes.Data)] //TODO: Figure out how to test this
+ [InlineData(PngChunkTypes.End)]
+ public void Decode_IncorrectCRCForCriticalChunk_ExceptionIsThrown(string chunkName)
+ {
+ using (var memStream = new MemoryStream())
+ {
+ memStream.Skip(8);
+
+ WriteChunk(memStream, chunkName);
+
+ CompressStream(memStream);
+
+ var decoder = new PngDecoder();
+
+ ImageFormatException exception = Assert.Throws(() =>
+ {
+ decoder.Decode(null, memStream);
+ });
+
+ Assert.Equal($"CRC Error. PNG {chunkName} chunk is corrupt!", exception.Message);
+ }
+ }
+
+ [Theory]
+ [InlineData(PngChunkTypes.Gamma)]
+ [InlineData(PngChunkTypes.PaletteAlpha)]
+ [InlineData(PngChunkTypes.Physical)]
+ //[InlineData(PngChunkTypes.Text)] //TODO: Figure out how to test this
+ public void Decode_IncorrectCRCForNonCriticalChunk_ExceptionIsThrown(string chunkName)
+ {
+ using (var memStream = new MemoryStream())
+ {
+ memStream.Skip(8);
+
+ WriteChunk(memStream, chunkName);
+
+ CompressStream(memStream);
+
+ var decoder = new PngDecoder();
+ decoder.Decode(null, memStream);
+ }
+ }
+
+ private static void WriteChunk(MemoryStream memStream, string chunkName)
+ {
+ memStream.Write(new byte[] { 0, 0, 0, 1 }, 0, 4);
+ memStream.Write(Encoding.GetEncoding("ASCII").GetBytes(chunkName), 0, 4);
+ memStream.Write(new byte[] { 0, 0, 0, 0, 0 }, 0, 5);
+ }
+
+ private static void CompressStream(Stream stream)
+ {
+ stream.Position = 0;
+ using (var deflateStream = new DeflateStream(stream, CompressionLevel.NoCompression, true))
+ {
+ }
+ stream.Position = 0;
+ }
}
}
\ No newline at end of file