Skip to content

Commit 803b4a2

Browse files
authored
Merge PR #387: Better handle baseStreams closing themselves unexpectedly
* Unit test for issue #379 * Change InflaterInputBuffer.Fill() to stop trying to read from inputStream in its CanRead property is false.
1 parent 6ee0f12 commit 803b4a2

File tree

3 files changed

+82
-2
lines changed

3 files changed

+82
-2
lines changed

src/ICSharpCode.SharpZipLib/Zip/Compression/Streams/InflaterInputStream.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ public void Fill()
116116
rawLength = 0;
117117
int toRead = rawData.Length;
118118

119-
while (toRead > 0)
119+
while (toRead > 0 && inputStream.CanRead)
120120
{
121121
int count = inputStream.Read(rawData, rawLength, toRead);
122122
if (count <= 0)

test/ICSharpCode.SharpZipLib.Tests/GZip/GZipTests.cs

+33-1
Original file line numberDiff line numberDiff line change
@@ -390,9 +390,41 @@ public void SmallBufferDecompression()
390390

391391

392392
}
393+
}
394+
393395
}
394396

395-
}
397+
/// <summary>
398+
/// Should gracefully handle reading from a stream that becomes unreadable after
399+
/// all of the data has been read.
400+
/// </summary>
401+
/// <remarks>
402+
/// Test for https://github.com/icsharpcode/SharpZipLib/issues/379
403+
/// </remarks>
404+
[Test]
405+
[Category("Zip")]
406+
public void ShouldGracefullyHandleReadingANonReableStream()
407+
{
408+
MemoryStream ms = new SelfClosingStream();
409+
using (var gzos = new GZipOutputStream(ms))
410+
{
411+
gzos.IsStreamOwner = false;
412+
413+
byte[] buf = new byte[100000];
414+
var rnd = new Random();
415+
rnd.NextBytes(buf);
416+
417+
gzos.Write(buf, 0, buf.Length);
418+
}
419+
420+
ms.Seek(0, SeekOrigin.Begin);
421+
422+
using (var gzis = new GZipInputStream(ms))
423+
using (var msRaw = new MemoryStream())
424+
{
425+
gzis.CopyTo(msRaw);
426+
}
427+
}
396428

397429
[Test]
398430
[Category("GZip")]

test/ICSharpCode.SharpZipLib.Tests/TestSupport/Streams.cs

+48
Original file line numberDiff line numberDiff line change
@@ -539,4 +539,52 @@ public override int Read(byte[] buffer, int offset, int count)
539539
return base.Read(buffer, offset, count);
540540
}
541541
}
542+
543+
/// <summary>
544+
/// A stream that closes itself when all of its data is read.
545+
/// </summary>
546+
/// <remarks>
547+
/// Useful for testing issues such as https://github.com/icsharpcode/SharpZipLib/issues/379
548+
/// </remarks>
549+
internal class SelfClosingStream : MemoryStream
550+
{
551+
private bool isFullyRead = false;
552+
553+
/// <summary>
554+
/// Initializes a new instance of the <see cref="SelfClosingStream"/> class.
555+
/// </summary>
556+
public SelfClosingStream()
557+
{
558+
}
559+
560+
// <inheritdoc/>
561+
public override int Read(byte[] buffer, int offset, int count)
562+
{
563+
var read = base.Read(buffer, offset, count);
564+
565+
if (read == 0)
566+
{
567+
isFullyRead = true;
568+
Close();
569+
}
570+
571+
return read;
572+
}
573+
574+
/// <summary>
575+
/// CanRead is false if we're closed, or base.CanRead otherwise.
576+
/// </summary>
577+
public override bool CanRead
578+
{
579+
get
580+
{
581+
if (isFullyRead)
582+
{
583+
return false;
584+
}
585+
586+
return base.CanRead;
587+
}
588+
}
589+
}
542590
}

0 commit comments

Comments
 (0)