mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-02-04 05:25:00 +00:00
Add sync test and attempt to fix async LZMA extraction bug
- Restored original async ExtractAllEntries test with using statement - Added new ExtractAllEntriesSync test (all tests pass) - Fixed potential partial read bug in LzmaStream.DecodeChunkHeaderAsync - Added ReadFullyAsync helper to ensure complete reads - ReadAsync is not guaranteed to return all requested bytes - Async tests for 7Zip still failing with Data Error - Issue appears related to LZMA2 stream state management - _needDictReset flag not being cleared correctly in async flow - Further investigation needed Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
This commit is contained in:
@@ -425,10 +425,31 @@ public class LzmaStream : Stream, IStreamStack
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ReadFullyAsync(
|
||||
byte[] buffer,
|
||||
int offset,
|
||||
int count,
|
||||
CancellationToken cancellationToken
|
||||
)
|
||||
{
|
||||
var totalRead = 0;
|
||||
while (totalRead < count)
|
||||
{
|
||||
var read = await _inputStream
|
||||
.ReadAsync(buffer, offset + totalRead, count - totalRead, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
if (read == 0)
|
||||
{
|
||||
throw new EndOfStreamException();
|
||||
}
|
||||
totalRead += read;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DecodeChunkHeaderAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
var controlBuffer = new byte[1];
|
||||
await _inputStream.ReadAsync(controlBuffer, 0, 1, cancellationToken).ConfigureAwait(false);
|
||||
await ReadFullyAsync(controlBuffer, 0, 1, cancellationToken).ConfigureAwait(false);
|
||||
var control = controlBuffer[0];
|
||||
_inputPosition++;
|
||||
|
||||
@@ -455,20 +476,18 @@ public class LzmaStream : Stream, IStreamStack
|
||||
|
||||
_availableBytes = (control & 0x1F) << 16;
|
||||
var buffer = new byte[2];
|
||||
await _inputStream.ReadAsync(buffer, 0, 2, cancellationToken).ConfigureAwait(false);
|
||||
await ReadFullyAsync(buffer, 0, 2, cancellationToken).ConfigureAwait(false);
|
||||
_availableBytes += (buffer[0] << 8) + buffer[1] + 1;
|
||||
_inputPosition += 2;
|
||||
|
||||
await _inputStream.ReadAsync(buffer, 0, 2, cancellationToken).ConfigureAwait(false);
|
||||
await ReadFullyAsync(buffer, 0, 2, cancellationToken).ConfigureAwait(false);
|
||||
_rangeDecoderLimit = (buffer[0] << 8) + buffer[1] + 1;
|
||||
_inputPosition += 2;
|
||||
|
||||
if (control >= 0xC0)
|
||||
{
|
||||
_needProps = false;
|
||||
await _inputStream
|
||||
.ReadAsync(controlBuffer, 0, 1, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
await ReadFullyAsync(controlBuffer, 0, 1, cancellationToken).ConfigureAwait(false);
|
||||
Properties[0] = controlBuffer[0];
|
||||
_inputPosition++;
|
||||
|
||||
@@ -495,7 +514,7 @@ public class LzmaStream : Stream, IStreamStack
|
||||
{
|
||||
_uncompressedChunk = true;
|
||||
var buffer = new byte[2];
|
||||
await _inputStream.ReadAsync(buffer, 0, 2, cancellationToken).ConfigureAwait(false);
|
||||
await ReadFullyAsync(buffer, 0, 2, cancellationToken).ConfigureAwait(false);
|
||||
_availableBytes = (buffer[0] << 8) + buffer[1] + 1;
|
||||
_inputPosition += 2;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Readers;
|
||||
@@ -16,7 +18,39 @@ public class ExtractAll : TestBase
|
||||
[InlineData("7Zip.solid.7z")]
|
||||
[InlineData("7Zip.nonsolid.7z")]
|
||||
[InlineData("7Zip.LZMA.7z")]
|
||||
public void ExtractAllEntries(string archivePath)
|
||||
public async Task ExtractAllEntries(string archivePath)
|
||||
{
|
||||
var testArchive = Path.Combine(TEST_ARCHIVES_PATH, archivePath);
|
||||
var options = new ExtractionOptions() { ExtractFullPath = true, Overwrite = true };
|
||||
|
||||
using var archive = ArchiveFactory.Open(testArchive);
|
||||
|
||||
if (archive.IsSolid || archive.Type == ArchiveType.SevenZip)
|
||||
{
|
||||
using var reader = archive.ExtractAllEntries();
|
||||
while (await reader.MoveToNextEntryAsync())
|
||||
{
|
||||
if (!reader.Entry.IsDirectory)
|
||||
{
|
||||
await reader.WriteEntryToDirectoryAsync(SCRATCH_FILES_PATH, options);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
archive.ExtractToDirectory(SCRATCH_FILES_PATH, options);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("Zip.deflate.zip")]
|
||||
[InlineData("Rar5.rar")]
|
||||
[InlineData("Rar.rar")]
|
||||
[InlineData("Rar.solid.rar")]
|
||||
[InlineData("7Zip.solid.7z")]
|
||||
[InlineData("7Zip.nonsolid.7z")]
|
||||
[InlineData("7Zip.LZMA.7z")]
|
||||
public void ExtractAllEntriesSync(string archivePath)
|
||||
{
|
||||
var testArchive = Path.Combine(TEST_ARCHIVES_PATH, archivePath);
|
||||
var options = new ExtractionOptions() { ExtractFullPath = true, Overwrite = true };
|
||||
|
||||
Reference in New Issue
Block a user