From dbc5c76eb1e43a694b34eb616c547121be8952ea Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Sun, 8 Sep 2019 22:49:42 +1000 Subject: [PATCH 1/2] Fix #1004 --- src/ImageSharp/Formats/Png/PngDecoderCore.cs | 38 ++++++++++++++---- .../Formats/Png/Zlib/ZlibInflateStream.cs | 36 +++++++++++++---- .../Formats/Png/PngDecoderTests.cs | 3 +- tests/ImageSharp.Tests/TestImages.cs | 1 + .../Images/Input/Png/zlib-ztxt-bad-header.png | Bin 0 -> 22781 bytes 5 files changed, 61 insertions(+), 17 deletions(-) create mode 100644 tests/Images/Input/Png/zlib-ztxt-bad-header.png diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs index 9bc5a5079..a9e588f6e 100644 --- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs @@ -175,11 +175,18 @@ namespace SixLabors.ImageSharp.Formats.Png this.InitializeImage(metadata, out image); } - using (var deframeStream = new ZlibInflateStream(this.currentStream, this.ReadNextDataChunk)) + var deframeStream = new ZlibInflateStream(this.currentStream, this.ReadNextDataChunk); + try { - deframeStream.AllocateNewBytes(chunk.Length); + deframeStream.AllocateNewBytes(chunk.Length, true); this.ReadScanlines(deframeStream.CompressedStream, image.Frames.RootFrame, pngMetadata); } + finally + { + // If an invalid Zlib stream is discovered the decoder will throw an exception + // due to the critical nature of the data chunk. + deframeStream.Dispose(); + } break; case PngChunkType.Palette: @@ -924,7 +931,11 @@ namespace SixLabors.ImageSharp.Formats.Png } ReadOnlySpan compressedData = data.Slice(zeroIndex + 2); - metadata.TextData.Add(new PngTextData(name, this.UncompressTextData(compressedData, PngConstants.Encoding), string.Empty, string.Empty)); + + if (this.TryUncompressTextData(compressedData, PngConstants.Encoding, out string uncompressed)) + { + metadata.TextData.Add(new PngTextData(name, uncompressed, string.Empty, string.Empty)); + } } /// @@ -987,7 +998,11 @@ namespace SixLabors.ImageSharp.Formats.Png if (compressionFlag == 1) { ReadOnlySpan compressedData = data.Slice(dataStartIdx); - metadata.TextData.Add(new PngTextData(keyword, this.UncompressTextData(compressedData, PngConstants.TranslatedEncoding), language, translatedKeyword)); + + if (this.TryUncompressTextData(compressedData, PngConstants.TranslatedEncoding, out string uncompressed)) + { + metadata.TextData.Add(new PngTextData(keyword, uncompressed, language, translatedKeyword)); + } } else { @@ -1001,13 +1016,19 @@ namespace SixLabors.ImageSharp.Formats.Png /// /// Compressed text data bytes. /// The string encoding to use. - /// A string. - private string UncompressTextData(ReadOnlySpan compressedData, Encoding encoding) + /// The uncompressed value. + /// The . + private bool TryUncompressTextData(ReadOnlySpan compressedData, Encoding encoding, out string value) { using (var memoryStream = new MemoryStream(compressedData.ToArray())) using (var inflateStream = new ZlibInflateStream(memoryStream, () => 0)) { - inflateStream.AllocateNewBytes(compressedData.Length); + if (!inflateStream.AllocateNewBytes(compressedData.Length, false)) + { + value = null; + return false; + } + var uncompressedBytes = new List(); // Note: this uses the a buffer which is only 4 bytes long to read the stream, maybe allocating a larger buffer makes sense here. @@ -1018,7 +1039,8 @@ namespace SixLabors.ImageSharp.Formats.Png bytesRead = inflateStream.CompressedStream.Read(this.buffer, 0, this.buffer.Length); } - return encoding.GetString(uncompressedBytes.ToArray()); + value = encoding.GetString(uncompressedBytes.ToArray()); + return true; } } diff --git a/src/ImageSharp/Formats/Png/Zlib/ZlibInflateStream.cs b/src/ImageSharp/Formats/Png/Zlib/ZlibInflateStream.cs index 405eeafeb..df0e72332 100644 --- a/src/ImageSharp/Formats/Png/Zlib/ZlibInflateStream.cs +++ b/src/ImageSharp/Formats/Png/Zlib/ZlibInflateStream.cs @@ -87,13 +87,17 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib /// Adds new bytes from a frame found in the original stream /// /// blabla - public void AllocateNewBytes(int bytes) + /// Whether the chunk to be inflated is a critical chunk. + /// The . + public bool AllocateNewBytes(int bytes, bool isCriticalChunk) { this.currentDataRemaining = bytes; if (this.compressedStream is null) { - this.InitializeInflateStream(); + return this.InitializeInflateStream(isCriticalChunk); } + + return true; } /// @@ -197,7 +201,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib this.isDisposed = true; } - private void InitializeInflateStream() + private bool InitializeInflateStream(bool isCriticalChunk) { // Read the zlib header : http://tools.ietf.org/html/rfc1950 // CMF(Compression Method and flags) @@ -215,7 +219,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib this.currentDataRemaining -= 2; if (cmf == -1 || flag == -1) { - return; + return false; } if ((cmf & 0x0F) == 8) @@ -225,14 +229,28 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib if (cinfo > 7) { - // Values of CINFO above 7 are not allowed in RFC1950. - // CINFO is not defined in this specification for CM not equal to 8. - throw new ImageFormatException($"Invalid window size for ZLIB header: cinfo={cinfo}"); + if (isCriticalChunk) + { + // Values of CINFO above 7 are not allowed in RFC1950. + // CINFO is not defined in this specification for CM not equal to 8. + throw new ImageFormatException($"Invalid window size for ZLIB header: cinfo={cinfo}"); + } + else + { + return false; + } } } else { - throw new ImageFormatException($"Bad method for ZLIB header: cmf={cmf}"); + if (isCriticalChunk) + { + throw new ImageFormatException($"Bad method for ZLIB header: cmf={cmf}"); + } + else + { + return false; + } } // The preset dictionary. @@ -247,6 +265,8 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib // Initialize the deflate Stream. this.compressedStream = new DeflateStream(this, CompressionMode.Decompress, true); + + return true; } } } diff --git a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs index 2e9fd7481..91b1ef2c1 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs @@ -40,7 +40,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png TestImages.Png.GrayAlpha8Bit, TestImages.Png.Gray1BitTrans, TestImages.Png.Bad.ZlibOverflow, - TestImages.Png.Bad.ZlibOverflow2 + TestImages.Png.Bad.ZlibOverflow2, + TestImages.Png.Bad.ZlibZtxtBadHeader, }; public static readonly string[] TestImages48Bpp = diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index e95ce0907..163d09bdd 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -90,6 +90,7 @@ namespace SixLabors.ImageSharp.Tests public const string CorruptedChunk = "Png/big-corrupted-chunk.png"; 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 static readonly string[] All = diff --git a/tests/Images/Input/Png/zlib-ztxt-bad-header.png b/tests/Images/Input/Png/zlib-ztxt-bad-header.png new file mode 100644 index 0000000000000000000000000000000000000000..c13f98fd16ed8318e88c2e550f31cca566aabdf9 GIT binary patch literal 22781 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 Date: Tue, 10 Sep 2019 17:34:14 +1000 Subject: [PATCH 2/2] Clean up scanline decoding code. --- src/ImageSharp/Formats/Png/PngDecoderCore.cs | 38 ++++++++---------- .../Formats/Png/Zlib/ZlibInflateStream.cs | 40 +++++++++++-------- 2 files changed, 40 insertions(+), 38 deletions(-) diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs index a9e588f6e..037f648f0 100644 --- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs @@ -5,6 +5,7 @@ using System; using System.Buffers.Binary; using System.Collections.Generic; using System.IO; +using System.IO.Compression; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; @@ -175,18 +176,7 @@ namespace SixLabors.ImageSharp.Formats.Png this.InitializeImage(metadata, out image); } - var deframeStream = new ZlibInflateStream(this.currentStream, this.ReadNextDataChunk); - try - { - deframeStream.AllocateNewBytes(chunk.Length, true); - this.ReadScanlines(deframeStream.CompressedStream, image.Frames.RootFrame, pngMetadata); - } - finally - { - // If an invalid Zlib stream is discovered the decoder will throw an exception - // due to the critical nature of the data chunk. - deframeStream.Dispose(); - } + this.ReadScanlines(chunk, image.Frames.RootFrame, pngMetadata); break; case PngChunkType.Palette: @@ -472,19 +462,25 @@ namespace SixLabors.ImageSharp.Formats.Png /// Reads the scanlines within the image. /// /// The pixel format. - /// The containing data. + /// The png chunk containing the compressed scanline data. /// The pixel data. /// The png metadata - private void ReadScanlines(Stream dataStream, ImageFrame image, PngMetadata pngMetadata) + private void ReadScanlines(PngChunk chunk, ImageFrame image, PngMetadata pngMetadata) where TPixel : struct, IPixel { - if (this.header.InterlaceMethod == PngInterlaceMode.Adam7) - { - this.DecodeInterlacedPixelData(dataStream, image, pngMetadata); - } - else + using (var deframeStream = new ZlibInflateStream(this.currentStream, this.ReadNextDataChunk)) { - this.DecodePixelData(dataStream, image, pngMetadata); + deframeStream.AllocateNewBytes(chunk.Length, true); + DeflateStream dataStream = deframeStream.CompressedStream; + + if (this.header.InterlaceMethod == PngInterlaceMode.Adam7) + { + this.DecodeInterlacedPixelData(dataStream, image, pngMetadata); + } + else + { + this.DecodePixelData(dataStream, image, pngMetadata); + } } } @@ -1021,7 +1017,7 @@ namespace SixLabors.ImageSharp.Formats.Png private bool TryUncompressTextData(ReadOnlySpan compressedData, Encoding encoding, out string value) { using (var memoryStream = new MemoryStream(compressedData.ToArray())) - using (var inflateStream = new ZlibInflateStream(memoryStream, () => 0)) + using (var inflateStream = new ZlibInflateStream(memoryStream)) { if (!inflateStream.AllocateNewBytes(compressedData.Length, false)) { diff --git a/src/ImageSharp/Formats/Png/Zlib/ZlibInflateStream.cs b/src/ImageSharp/Formats/Png/Zlib/ZlibInflateStream.cs index df0e72332..e4645c44a 100644 --- a/src/ImageSharp/Formats/Png/Zlib/ZlibInflateStream.cs +++ b/src/ImageSharp/Formats/Png/Zlib/ZlibInflateStream.cs @@ -20,14 +20,14 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib private static readonly byte[] ChecksumBuffer = new byte[4]; /// - /// The inner raw memory stream + /// A default delegate to get more data from the inner stream. /// - private readonly Stream innerStream; + private static readonly Func GetDataNoOp = () => 0; /// - /// The compressed stream sitting over the top of the deframer + /// The inner raw memory stream /// - private DeflateStream compressedStream; + private readonly Stream innerStream; /// /// A value indicating whether this instance of the given entity has been disposed. @@ -55,8 +55,17 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib /// /// Initializes a new instance of the class. /// - /// The inner raw stream - /// A delegate to get more data from the inner stream + /// The inner raw stream. + public ZlibInflateStream(Stream innerStream) + : this(innerStream, GetDataNoOp) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The inner raw stream. + /// A delegate to get more data from the inner stream. public ZlibInflateStream(Stream innerStream, Func getData) { this.innerStream = innerStream; @@ -76,12 +85,12 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib public override long Length => throw new NotSupportedException(); /// - public override long Position { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } + public override long Position { get => throw new NotSupportedException(); set => throw new NotSupportedException(); } /// /// Gets the compressed stream over the deframed inner stream /// - public DeflateStream CompressedStream => this.compressedStream; + public DeflateStream CompressedStream { get; private set; } /// /// Adds new bytes from a frame found in the original stream @@ -92,7 +101,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib public bool AllocateNewBytes(int bytes, bool isCriticalChunk) { this.currentDataRemaining = bytes; - if (this.compressedStream is null) + if (this.CompressedStream is null) { return this.InitializeInflateStream(isCriticalChunk); } @@ -101,10 +110,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib } /// - public override void Flush() - { - throw new NotSupportedException(); - } + public override void Flush() => throw new NotSupportedException(); /// public override int ReadByte() @@ -186,10 +192,10 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib if (disposing) { // dispose managed resources - if (this.compressedStream != null) + if (this.CompressedStream != null) { - this.compressedStream.Dispose(); - this.compressedStream = null; + this.CompressedStream.Dispose(); + this.CompressedStream = null; } } @@ -264,7 +270,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib } // Initialize the deflate Stream. - this.compressedStream = new DeflateStream(this, CompressionMode.Decompress, true); + this.CompressedStream = new DeflateStream(this, CompressionMode.Decompress, true); return true; }