Browse Source

Only throw exceptions when the CRC of a critical chunk is incorrect.

af/merge-core
Dirk Lemstra 9 years ago
parent
commit
9be8649a8e
  1. 13
      src/ImageSharp/Formats/Png/PngDecoderCore.cs
  2. 87
      tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs

13
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;
}
/// <summary>
/// Reads the data chunk containing physical dimension data.
/// </summary>
@ -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!");
}
}

87
tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs

@ -3,14 +3,15 @@
// Licensed under the Apache License, Version 2.0.
// </copyright>
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<Rgba32> 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<Rgba32> 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<Rgba32> 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<ImageFormatException>(() =>
{
decoder.Decode<Rgb24>(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<Rgb24>(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;
}
}
}
Loading…
Cancel
Save