diff --git a/src/ImageSharp/Formats/Png/Zlib/ZlibInflateStream.cs b/src/ImageSharp/Formats/Png/Zlib/ZlibInflateStream.cs
index 36d1d62e7..fd9c4ac63 100644
--- a/src/ImageSharp/Formats/Png/Zlib/ZlibInflateStream.cs
+++ b/src/ImageSharp/Formats/Png/Zlib/ZlibInflateStream.cs
@@ -2,10 +2,8 @@
// Licensed under the Apache License, Version 2.0.
using System;
-using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
-using System.Text;
namespace SixLabors.ImageSharp.Formats.Png.Zlib
{
@@ -14,6 +12,13 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
///
internal sealed class ZlibInflateStream : Stream
{
+ ///
+ /// Used to read the Adler-32 and Crc-32 checksums
+ /// We don't actually use this for anything so it doesn't
+ /// have to be threadsafe.
+ ///
+ private static readonly byte[] ChecksumBuffer = new byte[4];
+
///
/// The inner raw memory stream
///
@@ -38,9 +43,9 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
private bool isDisposed;
///
- /// The read crc data.
+ /// Whether the crc value has been read.
///
- private byte[] crcread;
+ private bool crcRead;
///
/// The current data remaining to be read
@@ -149,14 +154,12 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
this.compressedStream.Dispose();
this.compressedStream = null;
- if (this.crcread == null)
+ if (!this.crcRead)
{
// Consume the trailing 4 bytes
- this.crcread = new byte[4];
- for (int i = 0; i < 4; i++)
- {
- this.crcread[i] = (byte)this.innerStream.ReadByte();
- }
+ this.innerStream.Read(ChecksumBuffer, 0, 4);
+ this.currentDataRemaining -= 4;
+ this.crcRead = true;
}
}
}
@@ -171,11 +174,6 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
private void InitializeInflateStream()
{
- // The DICT dictionary identifier identifying the used dictionary.
-
- // The preset dictionary.
- bool fdict;
-
// Read the zlib header : http://tools.ietf.org/html/rfc1950
// CMF(Compression Method and flags)
// This byte is divided into a 4 - bit compression method and a
@@ -195,30 +193,35 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
return;
}
- if ((cmf & 0x0f) != 8)
+ if ((cmf & 0x0F) == 8)
{
- throw new Exception($"Bad compression method for ZLIB header: cmf={cmf}");
- }
+ // CINFO is the base-2 logarithm of the LZ77 window size, minus eight.
+ int cinfo = (cmf & 0xF0) >> 4;
- // CINFO is the base-2 logarithm of the LZ77 window size, minus eight.
- // int cinfo = ((cmf & (0xf0)) >> 8);
- fdict = (flag & 32) != 0;
+ 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}");
+ }
+ }
+ else
+ {
+ throw new ImageFormatException($"Bad method for ZLIB header: cmf={cmf}");
+ }
+ // The preset dictionary.
+ bool fdict = (flag & 32) != 0;
if (fdict)
{
- // The DICT dictionary identifier identifying the used dictionary.
- byte[] dictId = new byte[4];
-
- for (int i = 0; i < 4; i++)
- {
- // We consume but don't use this.
- dictId[i] = (byte)this.innerStream.ReadByte();
- this.currentDataRemaining--;
- }
+ // We don't need this for inflate so simply skip by the next four bytes.
+ // https://tools.ietf.org/html/rfc1950#page-6
+ this.innerStream.Read(ChecksumBuffer, 0, 4);
+ this.currentDataRemaining -= 4;
}
// Initialize the deflate Stream.
this.compressedStream = new DeflateStream(this, CompressionMode.Decompress, true);
}
}
-}
+}
\ No newline at end of file