Skip to content

Fix IncompleteArchiveException when enumerating compressed tar archives via ArchiveFactory.OpenArchive#1278

Draft
Copilot wants to merge 2 commits into
releasefrom
copilot/fix-unable-to-decompress-tar-files
Draft

Fix IncompleteArchiveException when enumerating compressed tar archives via ArchiveFactory.OpenArchive#1278
Copilot wants to merge 2 commits into
releasefrom
copilot/fix-unable-to-decompress-tar-files

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 8, 2026

ArchiveFactory.OpenArchive threw IncompleteArchiveException: Failed to read TAR header after the second entry when opening any compressed tar (.tar.gz, .tar.bz2, .tar.xz, .tar.zst). Uncompressed .tar files were unaffected.

Root cause

In StreamingMode.Streaming (used for all compressed tars), TarHeaderFactory.ReadHeader created a TarReadOnlySubStream wrapping 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 previous TarReadOnlySubStream in a local variable and Dispose/DisposeAsync it before reading the next header. TarReadOnlySubStream.Dispose skips unread data + 512-byte alignment padding; the existing _isDisposed guard makes double-dispose safe.

  • TarArchive.LoadEntries / LoadEntriesAsync — Split LongName handling by 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. Seekable (uncompressed) mode retains the existing post-read behaviour.

Usage

// Previously threw IncompleteArchiveException after the second entry
using var stream = File.OpenRead("archive.tar.gz");
using var archive = ArchiveFactory.OpenArchive(stream);

foreach (var entry in archive.Entries)          // now enumerates all entries
{
    if (!entry.IsDirectory)
        entry.OpenEntryStream().CopyTo(destination); // read content during iteration
}

Note: compressed tars are streaming-only — entry content must be read in iteration order, not after collecting all entries up front.

…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
Copilot AI requested a review from adamhathcock April 8, 2026 08:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Unable to decompress compressed tar files with ArchiveFactory.OpenArchive

2 participants