another sync over async

This commit is contained in:
Adam Hathcock
2026-02-04 11:26:47 +00:00
parent 94716a5ba9
commit b93ed79ef3
4 changed files with 39 additions and 20 deletions

View File

@@ -1,4 +1,5 @@
using System;
using System.Buffers;
using System.Buffers.Binary;
using System.IO;
using System.Security.Cryptography;
@@ -18,15 +19,17 @@ internal partial class WinzipAesCryptoStream : Stream
private bool _isFinalBlock;
private long _totalBytesLeftToRead;
private bool _isDisposed;
private bool _useSyncOverAsyncDispose;
internal WinzipAesCryptoStream(
Stream stream,
WinzipAesEncryptionData winzipAesEncryptionData,
long length
)
long length,
bool useSyncOverAsyncDispose)
{
_stream = stream;
_totalBytesLeftToRead = length;
_useSyncOverAsyncDispose = useSyncOverAsyncDispose;
#if DEBUG_STREAMS
this.DebugConstruct(typeof(WinzipAesCryptoStream));
@@ -75,20 +78,30 @@ internal partial class WinzipAesCryptoStream : Stream
if (disposing)
{
// Read out last 10 auth bytes - catch exceptions for async-only streams
try
{
Span<byte> ten = stackalloc byte[10];
_stream.ReadFully(ten);
}
catch (NotSupportedException)
{
// Stream may be async-only, auth bytes will be skipped
// This is acceptable when the entire stream has been read
}
if (_useSyncOverAsyncDispose)
{
var ten = ArrayPool<byte>.Shared.Rent(10);
try {
_stream.ReadFullyAsync(ten, 0, 10).GetAwaiter().GetResult();
} finally {
ArrayPool<byte>.Shared.Return(ten);
}
}
else
{
Span<byte> ten = stackalloc byte[10];
_stream.ReadFully(ten);
}
_stream.Dispose();
}
}
private async Task ReadAuthBytesAsync()
{
byte[] authBytes = new byte[10];
await _stream.ReadFullyAsync(authBytes, 0, 10).ConfigureAwait(false);
}
public override void Flush() { }
public override int Read(byte[] buffer, int offset, int count)

View File

@@ -99,10 +99,15 @@ internal abstract partial class ZipFilePart
{
if (Header.WinzipAesEncryptionData != null)
{
var useSyncOverAsync = false;
#if LEGACY_DOTNET
useSyncOverAsync = true;
#endif
return new WinzipAesCryptoStream(
plainStream,
Header.WinzipAesEncryptionData,
Header.CompressedSize - 10
Header.CompressedSize - 10,
useSyncOverAsync
);
}
return plainStream;

View File

@@ -270,7 +270,8 @@ internal abstract partial class ZipFilePart : FilePart
return new WinzipAesCryptoStream(
plainStream,
Header.WinzipAesEncryptionData,
Header.CompressedSize - 10
Header.CompressedSize - 10,
false
);
}
return plainStream;

View File

@@ -2,6 +2,7 @@ using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using SharpCompress.Archives;
using SharpCompress.Common;
using SharpCompress.IO;
using SharpCompress.Readers;
@@ -252,14 +253,14 @@ public class ZipReaderAsyncTests : ReaderTests
File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.WinzipAES.zip"))
)
)
using (
IReader baseReader = ZipReader.OpenReader(
await using (
var reader = await ReaderFactory.OpenAsyncReader(
stream,
new ReaderOptions { Password = "test" }
)
)
{
IAsyncReader reader = (IAsyncReader)baseReader;
while (await reader.MoveToNextEntryAsync())
{
if (!reader.Entry.IsDirectory)
@@ -284,14 +285,13 @@ public class ZipReaderAsyncTests : ReaderTests
File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "zipcrypto.zip"))
)
)
using (
IReader baseReader = ZipReader.OpenReader(
await using (
var reader = await ReaderFactory.OpenAsyncReader(
stream,
new ReaderOptions { Password = "test" }
)
)
{
IAsyncReader reader = (IAsyncReader)baseReader;
while (await reader.MoveToNextEntryAsync())
{
if (!reader.Entry.IsDirectory)