mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-11-15 17:02:03 +00:00
Handle partial LZip headers and validate dictionary sizes consistently
This commit is contained in:
@@ -129,11 +129,7 @@ public sealed partial class LZipStream
|
||||
var header = ArrayPool<byte>.Shared.Rent(6);
|
||||
try
|
||||
{
|
||||
var n = await stream.ReadAsync(header, 0, 6, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
// TODO: Handle reading only part of the header?
|
||||
|
||||
if (n != 6)
|
||||
if (!await stream.ReadFullyAsync(header, 0, 6, cancellationToken).ConfigureAwait(false))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -148,13 +144,7 @@ public sealed partial class LZipStream
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
var basePower = header[5] & 0x1F;
|
||||
var subtractionNumerator = (header[5] & 0xE0) >> 5;
|
||||
if (basePower < 4 || basePower > 30)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return (1 << basePower) - (subtractionNumerator * (1 << (basePower - 4)));
|
||||
return DecodeDictionarySize(header[5]);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
@@ -253,11 +253,7 @@ public sealed partial class LZipStream : Stream, IFinishable
|
||||
{
|
||||
// Read the header
|
||||
Span<byte> header = stackalloc byte[6];
|
||||
var n = stream.Read(header);
|
||||
|
||||
// TODO: Handle reading only part of the header?
|
||||
|
||||
if (n != 6)
|
||||
if (!stream.ReadFully(header))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -272,9 +268,18 @@ public sealed partial class LZipStream : Stream, IFinishable
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
var basePower = header[5] & 0x1F;
|
||||
var subtractionNumerator = (header[5] & 0xE0) >> 5;
|
||||
return (1 << basePower) - (subtractionNumerator * (1 << (basePower - 4)));
|
||||
return DecodeDictionarySize(header[5]);
|
||||
}
|
||||
|
||||
private static int DecodeDictionarySize(byte encoded)
|
||||
{
|
||||
var basePower = encoded & 0x1F;
|
||||
if (basePower < 12 || basePower > 29)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
var size = (1 << basePower) - ((encoded >> 5) * (1 << (basePower - 4)));
|
||||
return size >= 4096 ? size : 0;
|
||||
}
|
||||
|
||||
// Async methods moved to LZipStream.Async.cs
|
||||
|
||||
30
tests/SharpCompress.Test/Streams/LZipHeaderReadTests.cs
Normal file
30
tests/SharpCompress.Test/Streams/LZipHeaderReadTests.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using SharpCompress.Compressors.LZMA;
|
||||
using SharpCompress.Test.Mocks;
|
||||
using Xunit;
|
||||
|
||||
namespace SharpCompress.Test.Streams;
|
||||
|
||||
public class LZipHeaderReadTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(12, 4096)]
|
||||
[InlineData(29, 536870912)]
|
||||
[InlineData(11, 0)]
|
||||
[InlineData(30, 0)]
|
||||
[InlineData(31, 0)]
|
||||
[InlineData(44, 0)]
|
||||
public async Task LZip_Header_Fragmentation_And_Dictionary_Validation(int encoded, int expected)
|
||||
{
|
||||
byte[] header = [0x4C, 0x5A, 0x49, 0x50, 1, (byte)encoded];
|
||||
using var sync = new ShortReadStream(new MemoryStream(header));
|
||||
using var asyncInput = new ShortReadStream(new MemoryStream(header));
|
||||
Assert.Equal(expected, LZipStream.ValidateAndReadSize(sync));
|
||||
Assert.Equal(
|
||||
expected,
|
||||
await LZipStream.ValidateAndReadSizeAsync(asyncInput, CancellationToken.None)
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user