Fix IncompleteArchiveException when enumerating compressed tar archives via ArchiveFactory.OpenArchive#1278
Draft
Copilot wants to merge 2 commits into
Draft
Fix IncompleteArchiveException when enumerating compressed tar archives via ArchiveFactory.OpenArchive#1278Copilot wants to merge 2 commits into
Copilot wants to merge 2 commits into
Conversation
…rchive When reading compressed tar files (gzip, bzip2, xz, zstd, lzw, lzip) via ArchiveFactory.OpenArchive, entry enumeration would fail with IncompleteArchiveException after the second non-zero-sized entry. Root cause: TarHeaderFactory.ReadHeader (streaming mode) created a TarReadOnlySubStream for each entry's data but never disposed it before reading the next 512-byte header. This left the underlying decompressed stream positioned at the previous entry's data, causing header reads to read garbage. Fix: 1. TarHeaderFactory.ReadHeader / ReadHeaderAsync: track the previous TarReadOnlySubStream and dispose it (skipping any unread data + padding) before reading the next header. Double-dispose is safe because TarReadOnlySubStream guards against it with _isDisposed. 2. TarArchive.LoadEntries / LoadEntriesAsync: handle LongName entries differently for streaming (compressed) vs seekable (uncompressed) mode. In streaming mode the long filename is read immediately from header.PackedStream when the LongName header is received, before the foreach advances and ReadHeader disposes the packed stream. In seekable mode the existing behavior is preserved. Agent-Logs-Url: https://github.com/adamhathcock/sharpcompress/sessions/8feadf56-d10d-431f-834d-bf1237a577ec Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
Copilot
AI
changed the title
[WIP] Fix unable to decompress compressed tar files with ArchiveFactory.OpenArchive
Fix IncompleteArchiveException when enumerating compressed tar archives via ArchiveFactory.OpenArchive
Apr 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
ArchiveFactory.OpenArchivethrewIncompleteArchiveException: Failed to read TAR headerafter the second entry when opening any compressed tar (.tar.gz,.tar.bz2,.tar.xz,.tar.zst). Uncompressed.tarfiles were unaffected.Root cause
In
StreamingMode.Streaming(used for all compressed tars),TarHeaderFactory.ReadHeadercreated aTarReadOnlySubStreamwrapping each entry's data but never disposed it before looping back to read the next header. The underlying decompressed stream stayed positioned at the previous entry's data, not the next header block. The first directory entry (size=0) happened to work; any entry with non-zero data broke iteration of the next.Changes
TarHeaderFactory.ReadHeader/ReadHeaderAsync— Track the previousTarReadOnlySubStreamin a local variable andDispose/DisposeAsyncit before reading the next header.TarReadOnlySubStream.Disposeskips unread data + 512-byte alignment padding; the existing_isDisposedguard makes double-dispose safe.TarArchive.LoadEntries/LoadEntriesAsync— SplitLongNamehandling by mode. In streaming mode, the long filename is read immediately fromheader.PackedStreamwhen theLongNameheader is received—before theforeachadvances andReadHeaderdisposes the packed stream. Seekable (uncompressed) mode retains the existing post-read behaviour.Usage