mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-11-15 17:02:03 +00:00
Keep LZMA decoders retryable after dictionary limit rejection
This commit is contained in:
@@ -267,10 +267,12 @@ public partial class Decoder : ICoder, ISetDecoderProperties, IDisposable
|
||||
{
|
||||
throw new InvalidParamException();
|
||||
}
|
||||
_outWindow = new OutWindow();
|
||||
var blockSize = Math.Max(_dictionarySize, (1 << 12));
|
||||
DictionarySizeLimits.Validate(blockSize, DictionarySizeLimits.Lzma, "LZMA");
|
||||
_outWindow.Create(blockSize);
|
||||
// Publish only a usable window so a rejected dictionary can be retried.
|
||||
var window = new OutWindow();
|
||||
window.Create(blockSize);
|
||||
_outWindow = window;
|
||||
}
|
||||
|
||||
private void SetLiteralProperties(int lp, int lc)
|
||||
|
||||
@@ -119,6 +119,93 @@ public class DictionarySizeLimitTests : TestBase
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(false, false)]
|
||||
[InlineData(false, true)]
|
||||
[InlineData(true, false)]
|
||||
[InlineData(true, true)]
|
||||
public async Task Direct_Lzma_Decoder_Can_Retry_After_Limit_Rejection(bool useAsync, bool train)
|
||||
{
|
||||
using var limits = new DictionarySizeLimitScope();
|
||||
var expected = new byte[128];
|
||||
using var packed = new MemoryStream();
|
||||
byte[] properties;
|
||||
using (
|
||||
var encoder = LzmaStream.Create(new LzmaEncoderProperties(false, 4096), false, packed)
|
||||
)
|
||||
{
|
||||
properties = (byte[])encoder.Properties.Clone();
|
||||
encoder.Write(expected, 0, expected.Length);
|
||||
}
|
||||
packed.Position = 0;
|
||||
using var output = new MemoryStream();
|
||||
using var decoder = new Decoder();
|
||||
decoder.SetDecoderProperties(properties);
|
||||
DictionarySizeLimits.Lzma = 4095;
|
||||
|
||||
if (useAsync)
|
||||
{
|
||||
await Assert.ThrowsAsync<InvalidFormatException>(async () =>
|
||||
{
|
||||
if (train)
|
||||
{
|
||||
await decoder.TrainAsync(Stream.Null);
|
||||
}
|
||||
else
|
||||
{
|
||||
await decoder.CodeAsync(
|
||||
packed,
|
||||
output,
|
||||
packed.Length,
|
||||
expected.Length,
|
||||
null!,
|
||||
CancellationToken.None
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.Throws<InvalidFormatException>(() =>
|
||||
{
|
||||
if (train)
|
||||
{
|
||||
decoder.Train(Stream.Null);
|
||||
}
|
||||
else
|
||||
{
|
||||
decoder.Code(packed, output, packed.Length, expected.Length, null!);
|
||||
}
|
||||
});
|
||||
}
|
||||
Assert.Equal(0, packed.Position);
|
||||
DictionarySizeLimits.Lzma = 4096;
|
||||
if (useAsync)
|
||||
{
|
||||
if (train)
|
||||
{
|
||||
await decoder.TrainAsync(Stream.Null);
|
||||
}
|
||||
await decoder.CodeAsync(
|
||||
packed,
|
||||
output,
|
||||
packed.Length,
|
||||
expected.Length,
|
||||
null!,
|
||||
CancellationToken.None
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (train)
|
||||
{
|
||||
decoder.Train(Stream.Null);
|
||||
}
|
||||
decoder.Code(packed, output, packed.Length, expected.Length, null!);
|
||||
}
|
||||
Assert.Equal(expected, output.ToArray());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(false)]
|
||||
[InlineData(true)]
|
||||
|
||||
Reference in New Issue
Block a user