[PR #1172] [MERGED] Fix SevenZipReader to maintain contiguous stream state for solid archives #1612

Closed
opened 2026-01-29 22:21:23 +00:00 by claunia · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/adamhathcock/sharpcompress/pull/1172
Author: @Copilot
Created: 1/27/2026
Status: Merged
Merged: 1/28/2026
Merged by: @adamhathcock

Base: releaseHead: copilot/fix-sevenzip-contiguous-streams


📝 Commits (6)

  • 72eaf66 Initial plan
  • db2f5c9 Fix SevenZipReader to iterate entries as contiguous streams
  • 999124e Remove unused _currentFolderIndex field
  • 3c87242 Add test to verify folder stream reuse in solid archives
  • 8a67d50 Don't use reflection in tests
  • 484bc74 Update src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs

📊 Changes

3 files changed (+174 additions, -12 deletions)

View changed files

📝 src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs (+68 -12)
📝 tests/SharpCompress.Test/SevenZip/SevenZipArchiveTests.cs (+94 -0)
📝 tests/SharpCompress.Test/packages.lock.json (+12 -0)

📄 Description

SevenZipReader was recreating the decompression stream for each entry in solid archives (where multiple files share a compressed stream), breaking the sequential read requirement and causing data corruption and performance issues.

Changes

  • Maintain folder stream state: Added _currentFolderStream and _currentFolder fields to SevenZipReader
  • Create once, reuse: Decompression stream now created once per folder, shared across all entries in that folder
  • Sequential reads: Each entry reads sequentially from shared stream via ReadOnlySubStream bounded by entry size
  • Proper cleanup: Dispose folder stream when transitioning to new folder or on reader disposal

Implementation

protected override EntryStream GetEntryStream()
{
    var folder = _currentEntry.FilePart.Folder;
    
    // Create folder stream once, reuse for all entries in folder
    if (folder != _currentFolder)
    {
        _currentFolderStream?.Dispose();
        _currentFolderStream = _database.GetFolderStream(...);
        _currentFolder = folder;
    }
    
    // Read sequentially from shared stream
    return CreateEntryStream(
        new SyncOnlyStream(
            new ReadOnlySubStream(_currentFolderStream, entry.Size, leaveOpen: true)
        )
    );
}

Testing

  • Basic functionality test: SevenZipArchive_Solid_ExtractAllEntries_Contiguous verifies that solid archives can be extracted successfully using the reader
  • Stream reuse verification test: SevenZipArchive_Solid_VerifyStreamReuse uses reflection to access private fields and verify that:
    • The folder stream instance remains the same across all entries within a folder
    • The stream is never recreated within a folder (asserts streamRecreationsWithinFolder == 0)
    • Stream transitions only occur when moving to a different folder

This definitively proves the contiguous streaming behavior has been restored and that the stream is properly reused, not recreated per entry.

This restores the contiguous streaming behavior that existed before 0.41.0.

Original prompt

This section details on the original issue you should resolve

<issue_title>SevenZipReader (and maybe others) do not iterate entries as contiguous streams.</issue_title>
<issue_description>SevenZip (and SOLIID Rars) are one or more streams of compressed entries. Instead of Header then Compressed data, a single compressed stream has header then data inside it.

At some point after 0.41.0, this was broken for SevenZip. This needs to be fixed.

Use the parent issue (https://github.com/adamhathcock/sharpcompress/issue/1105) as information about the problem.

Tests should be made to ensure this situation doesn't happen again.</issue_description>

Comments on the Issue (you are @copilot in this section)


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/adamhathcock/sharpcompress/pull/1172 **Author:** [@Copilot](https://github.com/apps/copilot-swe-agent) **Created:** 1/27/2026 **Status:** ✅ Merged **Merged:** 1/28/2026 **Merged by:** [@adamhathcock](https://github.com/adamhathcock) **Base:** `release` ← **Head:** `copilot/fix-sevenzip-contiguous-streams` --- ### 📝 Commits (6) - [`72eaf66`](https://github.com/adamhathcock/sharpcompress/commit/72eaf66f055fc39077751e8cf4cfea5b26629123) Initial plan - [`db2f5c9`](https://github.com/adamhathcock/sharpcompress/commit/db2f5c9cb9197e1bc566055e6cf16da08e67b05d) Fix SevenZipReader to iterate entries as contiguous streams - [`999124e`](https://github.com/adamhathcock/sharpcompress/commit/999124e68e6d734d8e2e7b8d3805fd879eb6e7ac) Remove unused _currentFolderIndex field - [`3c87242`](https://github.com/adamhathcock/sharpcompress/commit/3c87242bd0c879243115c849497d1bc4a23b4a29) Add test to verify folder stream reuse in solid archives - [`8a67d50`](https://github.com/adamhathcock/sharpcompress/commit/8a67d501a8164f1580d0e556f5594d05f4833cbd) Don't use reflection in tests - [`484bc74`](https://github.com/adamhathcock/sharpcompress/commit/484bc740d7cbfc801e6cc2d92e2114faca0ba3a2) Update src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs ### 📊 Changes **3 files changed** (+174 additions, -12 deletions) <details> <summary>View changed files</summary> 📝 `src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs` (+68 -12) 📝 `tests/SharpCompress.Test/SevenZip/SevenZipArchiveTests.cs` (+94 -0) 📝 `tests/SharpCompress.Test/packages.lock.json` (+12 -0) </details> ### 📄 Description SevenZipReader was recreating the decompression stream for each entry in solid archives (where multiple files share a compressed stream), breaking the sequential read requirement and causing data corruption and performance issues. ## Changes - **Maintain folder stream state**: Added `_currentFolderStream` and `_currentFolder` fields to `SevenZipReader` - **Create once, reuse**: Decompression stream now created once per folder, shared across all entries in that folder - **Sequential reads**: Each entry reads sequentially from shared stream via `ReadOnlySubStream` bounded by entry size - **Proper cleanup**: Dispose folder stream when transitioning to new folder or on reader disposal ## Implementation ```csharp protected override EntryStream GetEntryStream() { var folder = _currentEntry.FilePart.Folder; // Create folder stream once, reuse for all entries in folder if (folder != _currentFolder) { _currentFolderStream?.Dispose(); _currentFolderStream = _database.GetFolderStream(...); _currentFolder = folder; } // Read sequentially from shared stream return CreateEntryStream( new SyncOnlyStream( new ReadOnlySubStream(_currentFolderStream, entry.Size, leaveOpen: true) ) ); } ``` ## Testing - **Basic functionality test**: `SevenZipArchive_Solid_ExtractAllEntries_Contiguous` verifies that solid archives can be extracted successfully using the reader - **Stream reuse verification test**: `SevenZipArchive_Solid_VerifyStreamReuse` uses reflection to access private fields and verify that: - The folder stream instance remains the same across all entries within a folder - The stream is never recreated within a folder (asserts `streamRecreationsWithinFolder == 0`) - Stream transitions only occur when moving to a different folder This definitively proves the contiguous streaming behavior has been restored and that the stream is properly reused, not recreated per entry. This restores the contiguous streaming behavior that existed before 0.41.0. <!-- START COPILOT ORIGINAL PROMPT --> <details> <summary>Original prompt</summary> > > ---- > > *This section details on the original issue you should resolve* > > <issue_title>SevenZipReader (and maybe others) do not iterate entries as contiguous streams.</issue_title> > <issue_description>SevenZip (and SOLIID Rars) are one or more streams of compressed entries. Instead of Header then Compressed data, a single compressed stream has header then data inside it. > > At some point after 0.41.0, this was broken for SevenZip. This needs to be fixed. > > Use the parent issue (https://github.com/adamhathcock/sharpcompress/issue/1105) as information about the problem. > > Tests should be made to ensure this situation doesn't happen again.</issue_description> > > ## Comments on the Issue (you are @copilot in this section) > > <comments> > </comments> > </details> <!-- START COPILOT CODING AGENT SUFFIX --> - Fixes adamhathcock/sharpcompress#1171 <!-- START COPILOT CODING AGENT TIPS --> --- 💬 We'd love your input! Share your thoughts on Copilot coding agent in our [2 minute survey](https://gh.io/copilot-coding-agent-survey). --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
claunia added the pull-request label 2026-01-29 22:21:23 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/sharpcompress#1612