Skip to content

XZBlock accessing Position for non seakable streams throws exception #1231

@SKProCH

Description

@SKProCH

Hello. Previously I used this code:

using var responseMessage = await Utils.HttpClient.GetAsync(fileLink,
    HttpCompletionOption.ResponseHeadersRead);
await using var responseStream = await responseMessage.Content.ReadAsStreamAsync();
await using var xzStream = new XZStream(responseStream);
await using var reader = new TarReader(xzStream, true);

To download the tar.xz file and uncompress it on the fly in memory. After updating to 0.46.2 if starts throwing exception:

System.NotSupportedException: Specified method is not supported.
   at System.Net.Http.HttpBaseStream.get_Position()
   at SharpCompress.Compressors.Xz.XZBlock..ctor(Stream stream, CheckType checkType, Int32 checkSize) in D:\a\sharpcompress\sharpcompress\src\SharpCompress\Compressors\Xz\XZBlock.cs:line 38
   at SharpCompress.Compressors.Xz.XZStream.NextBlock() in D:\a\sharpcompress\sharpcompress\src\SharpCompress\Compressors\Xz\XZStream.cs:line 133
   at SharpCompress.Compressors.Xz.XZStream.ReadBlocksAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken) in D:\a\sharpcompress\sharpcompress\src\SharpCompress\Compressors\Xz\XZStream.Async.cs:line 104
   at SharpCompress.Compressors.Xz.XZStream.ReadAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken) in D:\a\sharpcompress\sharpcompress\src\SharpCompress\Compressors\Xz\XZStream.Async.cs:line 52
   at System.IO.Stream.ReadAtLeastAsyncCore(Memory`1 buffer, Int32 minimumBytes, Boolean throwOnEndOfStream, CancellationToken cancellationToken)
   at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource.GetResult(Int16 token)
   at System.Formats.Tar.TarHeader.TryGetNextHeaderAsync(Stream archiveStream, Boolean copyData, TarEntryFormat initialFormat, Boolean processDataBlock, CancellationToken cancellationToken)
   at System.Formats.Tar.TarReader.TryGetNextEntryHeaderAsync(Boolean copyData, CancellationToken cancellationToken)
   at System.Formats.Tar.TarReader.GetNextEntryInternalAsync(Boolean copyData, CancellationToken cancellationToken)
...

This is caused by accessing the stream position

_startPosition = stream.Position;

which will throw in HttpBaseStream implementation. This is introduced in #878

I suppose that we need firstly check if the stream supports CanSeek and only after that accesing this variable, assuming padding is fine. Or just surround this by trycatch.

Metadata

Metadata

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions