diff --git a/src/ImageSharp/Formats/Png/Zlib/ZlibInflateStream.cs b/src/ImageSharp/Formats/Png/Zlib/ZlibInflateStream.cs
index e4645c44ac..3eb34b8617 100644
--- a/src/ImageSharp/Formats/Png/Zlib/ZlibInflateStream.cs
+++ b/src/ImageSharp/Formats/Png/Zlib/ZlibInflateStream.cs
@@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
internal sealed class ZlibInflateStream : Stream
{
///
- /// Used to read the Adler-32 and Crc-32 checksums
+ /// 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.
///
@@ -25,7 +25,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
private static readonly Func GetDataNoOp = () => 0;
///
- /// The inner raw memory stream
+ /// The inner raw memory stream.
///
private readonly Stream innerStream;
@@ -43,12 +43,12 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
private bool isDisposed;
///
- /// The current data remaining to be read
+ /// The current data remaining to be read.
///
private int currentDataRemaining;
///
- /// Delegate to get more data once we've exhausted the current data remaining
+ /// Delegate to get more data once we've exhausted the current data remaining.
///
private readonly Func getData;
@@ -88,14 +88,14 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
public override long Position { get => throw new NotSupportedException(); set => throw new NotSupportedException(); }
///
- /// Gets the compressed stream over the deframed inner stream
+ /// Gets the compressed stream over the deframed inner stream.
///
public DeflateStream CompressedStream { get; private set; }
///
- /// Adds new bytes from a frame found in the original stream
+ /// Adds new bytes from a frame found in the original stream.
///
- /// blabla
+ /// The current remaining data according to the chunk length.
/// Whether the chunk to be inflated is a critical chunk.
/// The .
public bool AllocateNewBytes(int bytes, bool isCriticalChunk)
@@ -124,7 +124,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
{
if (this.currentDataRemaining == 0)
{
- // last buffer was read in its entirety, let's make sure we don't actually have more
+ // Last buffer was read in its entirety, let's make sure we don't actually have more in additional IDAT chunks.
this.currentDataRemaining = this.getData();
if (this.currentDataRemaining == 0)
@@ -135,32 +135,35 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
int bytesToRead = Math.Min(count, this.currentDataRemaining);
this.currentDataRemaining -= bytesToRead;
- int bytesRead = this.innerStream.Read(buffer, offset, bytesToRead);
- long length = this.innerStream.Length;
+ int totalBytesRead = this.innerStream.Read(buffer, offset, bytesToRead);
+ long innerStreamLength = this.innerStream.Length;
- // Keep reading data until we've reached the end of the stream or filled the buffer
- while (this.currentDataRemaining == 0 && bytesRead < count)
+ // Keep reading data until we've reached the end of the stream or filled the buffer.
+ int bytesRead = 0;
+ offset += totalBytesRead;
+ while (this.currentDataRemaining == 0 && totalBytesRead < count)
{
this.currentDataRemaining = this.getData();
if (this.currentDataRemaining == 0)
{
- return bytesRead;
+ return totalBytesRead;
}
offset += bytesRead;
- if (offset >= length || offset >= count)
+ if (offset >= innerStreamLength || offset >= count)
{
- return bytesRead;
+ return totalBytesRead;
}
- bytesToRead = Math.Min(count - bytesRead, this.currentDataRemaining);
+ bytesToRead = Math.Min(count - totalBytesRead, this.currentDataRemaining);
this.currentDataRemaining -= bytesToRead;
- bytesRead += this.innerStream.Read(buffer, offset, bytesToRead);
+ bytesRead = this.innerStream.Read(buffer, offset, bytesToRead);
+ totalBytesRead += bytesRead;
}
- return bytesRead;
+ return totalBytesRead;
}
///
@@ -191,7 +194,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
if (disposing)
{
- // dispose managed resources
+ // Dispose managed resources.
if (this.CompressedStream != null)
{
this.CompressedStream.Dispose();
diff --git a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs
index 91b1ef2c17..2a76310fcd 100644
--- a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs
+++ b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs
@@ -75,6 +75,13 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
TestImages.Png.GrayAlpha8BitInterlaced
};
+ public static readonly string[] TestImagesIssue1014 =
+ {
+ TestImages.Png.Issue1014_1, TestImages.Png.Issue1014_2,
+ TestImages.Png.Issue1014_3, TestImages.Png.Issue1014_4,
+ TestImages.Png.Issue1014_5, TestImages.Png.Issue1014_6
+ };
+
[Theory]
[WithFileCollection(nameof(CommonTestImages), PixelTypes.Rgba32)]
public void Decode(TestImageProvider provider)
@@ -199,5 +206,22 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
Assert.Equal(expectedPixelSize, Image.Identify(stream)?.PixelType?.BitsPerPixel);
}
}
+
+ [Theory]
+ [WithFileCollection(nameof(TestImagesIssue1014), PixelTypes.Rgba32)]
+ public void Issue1014(TestImageProvider provider)
+ where TPixel : struct, IPixel
+ {
+ System.Exception ex = Record.Exception(
+ () =>
+ {
+ using (Image image = provider.GetImage(new PngDecoder()))
+ {
+ image.DebugSave(provider);
+ // TODO: compare to expected output
+ }
+ });
+ Assert.Null(ex);
+ }
}
}
diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs
index 163d09bdde..146f2efcdb 100644
--- a/tests/ImageSharp.Tests/TestImages.cs
+++ b/tests/ImageSharp.Tests/TestImages.cs
@@ -82,6 +82,14 @@ namespace SixLabors.ImageSharp.Tests
public const string Ducky = "Png/ducky.png";
public const string Rainbow = "Png/rainbow.png";
+ // Issue 1014: https://github.com/SixLabors/ImageSharp/issues/1014
+ public const string Issue1014_1 = "Png/issues/Issue_1014_1.png";
+ public const string Issue1014_2 = "Png/issues/Issue_1014_2.png";
+ public const string Issue1014_3 = "Png/issues/Issue_1014_3.png";
+ public const string Issue1014_4 = "Png/issues/Issue_1014_4.png";
+ public const string Issue1014_5 = "Png/issues/Issue_1014_5.png";
+ public const string Issue1014_6 = "Png/issues/Issue_1014_6.png";
+
public static class Bad
{
// Odd chunk lengths
diff --git a/tests/Images/Input/Png/issues/Issue_1014_1.png b/tests/Images/Input/Png/issues/Issue_1014_1.png
new file mode 100644
index 0000000000..2cbd401e61
Binary files /dev/null and b/tests/Images/Input/Png/issues/Issue_1014_1.png differ
diff --git a/tests/Images/Input/Png/issues/Issue_1014_2.png b/tests/Images/Input/Png/issues/Issue_1014_2.png
new file mode 100644
index 0000000000..ca1c8ea5b9
Binary files /dev/null and b/tests/Images/Input/Png/issues/Issue_1014_2.png differ
diff --git a/tests/Images/Input/Png/issues/Issue_1014_3.png b/tests/Images/Input/Png/issues/Issue_1014_3.png
new file mode 100644
index 0000000000..3a7a8ed2c0
Binary files /dev/null and b/tests/Images/Input/Png/issues/Issue_1014_3.png differ
diff --git a/tests/Images/Input/Png/issues/Issue_1014_4.png b/tests/Images/Input/Png/issues/Issue_1014_4.png
new file mode 100644
index 0000000000..54d099427d
Binary files /dev/null and b/tests/Images/Input/Png/issues/Issue_1014_4.png differ
diff --git a/tests/Images/Input/Png/issues/Issue_1014_5.png b/tests/Images/Input/Png/issues/Issue_1014_5.png
new file mode 100644
index 0000000000..9e719ca302
Binary files /dev/null and b/tests/Images/Input/Png/issues/Issue_1014_5.png differ
diff --git a/tests/Images/Input/Png/issues/Issue_1014_6.png b/tests/Images/Input/Png/issues/Issue_1014_6.png
new file mode 100644
index 0000000000..7b90f49da6
Binary files /dev/null and b/tests/Images/Input/Png/issues/Issue_1014_6.png differ