Skip to content

Commit bcda43b

Browse files
committed
Fix infinite loop in BrotliEncoder
1 parent ce4c03a commit bcda43b

2 files changed

Lines changed: 41 additions & 1 deletion

File tree

src/MemoryPack.Core/Compression/BrotliCompressor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ static int CompressCore<TBufferWriter>(ref BrotliEncoder encoder, ReadOnlySpan<b
262262
var lastResult = OperationStatus.DestinationTooSmall;
263263
while (lastResult == OperationStatus.DestinationTooSmall)
264264
{
265-
ref var spanRef = ref destBufferWriter.GetSpanReference(initialLength ?? source.Length);
265+
ref var spanRef = ref destBufferWriter.GetSpanReference(Math.Max(initialLength ?? source.Length, 1));
266266
var dest = MemoryMarshal.CreateSpan(ref spanRef, destBufferWriter.BufferLength);
267267

268268
lastResult = encoder.Compress(source, dest, out int bytesConsumed, out int bytesWritten, isFinalBlock: isFinalBlock);

tests/MemoryPack.Tests/BrotliTest.cs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
using MemoryPack.Compression;
22
using System;
3+
using System.Buffers;
4+
using System.IO.Compression;
35

46
namespace MemoryPack.Tests;
57

@@ -14,6 +16,44 @@ public void LargeByteArray()
1416
data.MemDecmpDeserialize(bin);
1517
}
1618

19+
[Fact]
20+
public void EncodeEmptyCntent()
21+
{
22+
var buffer = new ArrayBufferWriter<byte>();
23+
using var state = MemoryPackWriterOptionalStatePool.Rent(null);
24+
var writer = new MemoryPackWriter<ArrayBufferWriter<byte>>(ref buffer, state);
25+
26+
using var compressor = new BrotliCompressor(CompressionLevel.Fastest);
27+
compressor.CopyTo(ref writer);
28+
29+
using var decompressor = new BrotliDecompressor();
30+
decompressor.Decompress(compressor.ToArray()).ToArray().Should().BeEmpty();
31+
}
32+
33+
[Fact]
34+
public void EncodeEmptyFinalBlock()
35+
{
36+
using var state = MemoryPackWriterOptionalStatePool.Rent(null);
37+
38+
var compressor = new BrotliCompressor(CompressionLevel.Fastest);
39+
var coWriter = new MemoryPackWriter<BrotliCompressor>(ref compressor, state);
40+
41+
var bytes = new byte[248];
42+
Random.Shared.NextBytes(bytes);
43+
coWriter.WriteUnmanagedArray(bytes);
44+
coWriter.Flush();
45+
46+
var buffer = new ArrayBufferWriter<byte>();
47+
compressor.CopyTo(buffer);
48+
49+
using var readerState = MemoryPackReaderOptionalStatePool.Rent(null);
50+
using var decompressor = new BrotliDecompressor();
51+
var decompressed = decompressor.Decompress(compressor.ToArray());
52+
var reader = new MemoryPackReader(in decompressed, readerState);
53+
54+
reader.ReadArray<byte>().Should().BeEquivalentTo(bytes);
55+
compressor.Dispose();
56+
}
1757
}
1858

1959
[MemoryPackable]

0 commit comments

Comments
 (0)