Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/ICSharpCode.SharpZipLib/GZip/GzipInputStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,6 @@ public override int Read(byte[] buffer, int offset, int count)
// A compressed block could potentially be empty, so we need to loop until we reach EOF or
// we find data.
while (true) {

// If we haven't read the header for this block, read it
if (!readGZIPHeader) {

Expand Down Expand Up @@ -133,6 +132,9 @@ public override int Read(byte[] buffer, int offset, int count)
// If this is the end of stream, read the footer
if (inf.IsFinished) {
ReadFooter();
} else if (inf.RemainingInput == 0) {
// If the stream is not finished but we have no more data to read, don't keep looping forever
throw new GZipException("Unexpected EOF");
}

if (bytesRead > 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,7 @@ bool DeflateStored(bool flush, bool finish)

huffman.FlushStoredBlock(window, blockStart, storedLength, lastBlock);
blockStart += storedLength;
return !lastBlock;
return !(lastBlock || storedLength == 0);
}
return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,13 @@ protected void InitializeAESPassword(ZipEntry entry, string rawPassword,
/// </summary>
protected void Deflate()
{
while (!deflater_.IsNeedingInput) {
Deflate(false);
}

private void Deflate(bool flushing)
{
while (flushing || !deflater_.IsNeedingInput)
{
int deflateCount = deflater_.Deflate(buffer_, 0, buffer_.Length);

if (deflateCount <= 0) {
Expand Down Expand Up @@ -346,7 +352,7 @@ public override int Read(byte[] buffer, int offset, int count)
public override void Flush()
{
deflater_.Flush();
Deflate();
Deflate(true);
baseOutputStream_.Flush();
}

Expand Down
55 changes: 55 additions & 0 deletions test/ICSharpCode.SharpZipLib.Tests/GZip/GZipTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,61 @@ public void TrailingGarbage()
}
}

/// <summary>
/// Test that if we flush a GZip output stream then all data that has been written
/// is flushed through to the underlying stream and can be successfully read back
/// even if the stream is not yet finished.
/// </summary>
[Test]
[Category("GZip")]
public void FlushToUnderlyingStream()
{
var ms = new MemoryStream();
var outStream = new GZipOutputStream(ms);

byte[] buf = new byte[100000];
var rnd = new Random();
rnd.NextBytes(buf);

outStream.Write(buf, 0, buf.Length);
// Flush output stream but don't finish it yet
outStream.Flush();

ms.Seek(0, SeekOrigin.Begin);

var inStream = new GZipInputStream(ms);
byte[] buf2 = new byte[buf.Length];
int currentIndex = 0;
int count = buf2.Length;

while (true)
{
try
{
int numRead = inStream.Read(buf2, currentIndex, count);
if (numRead <= 0)
{
break;
}
currentIndex += numRead;
count -= numRead;
}
catch (GZipException)
{
// We should get an unexpected EOF exception once we've read all
// data as the stream isn't yet finished.
break;
}
}

Assert.AreEqual(0, count);

for (int i = 0; i < buf.Length; ++i)
{
Assert.AreEqual(buf2[i], buf[i]);
}
}

[Test]
[Category("GZip")]
[Category("Long Running")]
Expand Down