Skip to content

Commit ce0dcd5

Browse files
authored
Fix interop test. Dispose GZipStream before accessing content. (#637)
1 parent 542066a commit ce0dcd5

File tree

6 files changed

+48
-14
lines changed

6 files changed

+48
-14
lines changed

src/Grpc.AspNetCore.Server/Internal/HttpContextSerializationContext.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -225,13 +225,15 @@ private ReadOnlySpan<byte> CompressMessage(ReadOnlySpan<byte> messageData)
225225
GrpcServerLog.CompressingMessage(_serverCallContext.Logger, _compressionProvider.EncodingName);
226226

227227
var output = new MemoryStream();
228+
229+
// Compression stream must be disposed before its content is read.
230+
// GZipStream writes final Adler32 at the end of the stream on dispose.
228231
using (var compressionStream = _compressionProvider.CreateCompressionStream(output, _serverCallContext.MethodContext.ResponseCompressionLevel))
229232
{
230233
compressionStream.Write(messageData);
231-
compressionStream.Flush();
232-
233-
return output.GetBuffer().AsSpan(0, (int)output.Length);
234234
}
235+
236+
return output.GetBuffer().AsSpan(0, (int)output.Length);
235237
}
236238
}
237239
}

src/Grpc.AspNetCore.Server/Internal/PipeExtensions.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -409,10 +409,10 @@ private static bool TryDecompressMessage(ILogger logger, string compressionEncod
409409
using (var compressionStream = compressionProvider.CreateDecompressionStream(new ReadOnlySequenceStream(messageData)))
410410
{
411411
compressionStream.CopyTo(output);
412-
413-
result = new ReadOnlySequence<byte>(output.GetBuffer(), 0, (int)output.Length);
414-
return true;
415412
}
413+
414+
result = new ReadOnlySequence<byte>(output.GetBuffer(), 0, (int)output.Length);
415+
return true;
416416
}
417417

418418
result = null;

src/Grpc.Net.Client/Internal/StreamExtensions.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,8 +191,10 @@ private static bool TryDecompressMessage(ILogger logger, string compressionEncod
191191
GrpcCallLog.DecompressingMessage(logger, compressionProvider.EncodingName);
192192

193193
var output = new MemoryStream();
194-
var compressionStream = compressionProvider.CreateDecompressionStream(new MemoryStream(messageData));
195-
compressionStream.CopyTo(output);
194+
using (var compressionStream = compressionProvider.CreateDecompressionStream(new MemoryStream(messageData)))
195+
{
196+
compressionStream.CopyTo(output);
197+
}
196198

197199
result = new ReadOnlySequence<byte>(output.GetBuffer(), 0, (int)output.Length);
198200
return true;
@@ -282,6 +284,9 @@ private static byte[] CompressMessage(ILogger logger, string compressionEncoding
282284
GrpcCallLog.CompressingMessage(logger, compressionProvider.EncodingName);
283285

284286
var output = new MemoryStream();
287+
288+
// Compression stream must be disposed before its content is read.
289+
// GZipStream writes final Adler32 at the end of the stream.
285290
using (var compressionStream = compressionProvider.CreateCompressionStream(output, compressionLevel))
286291
{
287292
compressionStream.Write(messageData.Span);

src/Grpc.Net.Common/Compression/GzipCompressionProvider.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public GzipCompressionProvider(CompressionLevel defaultCompressionLevel)
5050
/// <returns>A stream used to compress data.</returns>
5151
public Stream CreateCompressionStream(Stream stream, CompressionLevel? compressionLevel)
5252
{
53-
return new GZipStream(stream, compressionLevel ?? _defaultCompressionLevel);
53+
return new GZipStream(stream, compressionLevel ?? _defaultCompressionLevel, leaveOpen: true);
5454
}
5555

5656
/// <summary>
@@ -60,7 +60,7 @@ public Stream CreateCompressionStream(Stream stream, CompressionLevel? compressi
6060
/// <returns>A stream used to decompress data.</returns>
6161
public Stream CreateDecompressionStream(Stream stream)
6262
{
63-
return new GZipStream(stream, CompressionMode.Decompress);
63+
return new GZipStream(stream, CompressionMode.Decompress, leaveOpen: true);
6464
}
6565
}
6666
}

test/FunctionalTests/Server/CompressionTests.cs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -345,12 +345,39 @@ private class DoesNotExistCompressionProvider : ICompressionProvider
345345

346346
public Stream CreateCompressionStream(Stream stream, System.IO.Compression.CompressionLevel? compressionLevel)
347347
{
348-
return stream;
348+
return new WrapperStream(stream);
349349
}
350350

351351
public Stream CreateDecompressionStream(Stream stream)
352352
{
353-
return stream;
353+
return new WrapperStream(stream);
354+
}
355+
356+
// Returned stream is disposed. Wrapper leaves the inner stream open.
357+
private class WrapperStream : Stream
358+
{
359+
private readonly Stream _innerStream;
360+
361+
public WrapperStream(Stream innerStream)
362+
{
363+
_innerStream = innerStream;
364+
}
365+
366+
public override bool CanRead => _innerStream.CanRead;
367+
public override bool CanSeek => _innerStream.CanSeek;
368+
public override bool CanWrite => _innerStream.CanWrite;
369+
public override long Length => _innerStream.Length;
370+
public override long Position
371+
{
372+
get => _innerStream.Position;
373+
set => _innerStream.Position = value;
374+
}
375+
376+
public override void Flush() => _innerStream.Flush();
377+
public override int Read(byte[] buffer, int offset, int count) => _innerStream.Read(buffer, offset, count);
378+
public override long Seek(long offset, SeekOrigin origin) => _innerStream.Seek(offset, origin);
379+
public override void SetLength(long value) => _innerStream.SetLength(value);
380+
public override void Write(byte[] buffer, int offset, int count) => _innerStream.Write(buffer, offset, count);
354381
}
355382
}
356383

test/Grpc.AspNetCore.Server.Tests/PipeExtensionsTestsBase.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -709,7 +709,7 @@ public async Task WriteMessageAsync_GzipCompressed_WriteCompressedData()
709709
var messageData = ms.ToArray();
710710

711711
Assert.AreEqual(1, messageData[0]); // compression
712-
Assert.AreEqual(17, messageData[4]); // message length
712+
Assert.AreEqual(21, messageData[4]); // message length
713713

714714
byte[] result = Decompress(compressionProviders["gzip"], messageData);
715715
Assert.AreEqual(1, result.Length);
@@ -747,7 +747,7 @@ public async Task WriteMessageAsync_HasCustomCompressionLevel_WriteCompressedDat
747747
var messageData = ms.ToArray();
748748

749749
Assert.AreEqual(1, messageData[0]); // compression
750-
Assert.AreEqual(17, messageData[4]); // message length
750+
Assert.AreEqual(21, messageData[4]); // message length
751751

752752
byte[] result = Decompress(mockCompressionProvider, messageData);
753753
Assert.AreEqual(1, result.Length);

0 commit comments

Comments
 (0)