Skip to content

Fix infinite loop in SourceStream.Seek for malformed archives#1178

Merged
adamhathcock merged 3 commits intoreleasefrom
copilot/fix-infinite-loop-rar-archive-again
Feb 2, 2026
Merged

Fix infinite loop in SourceStream.Seek for malformed archives#1178
adamhathcock merged 3 commits intoreleasefrom
copilot/fix-infinite-loop-rar-archive-again

Conversation

Copy link
Contributor

Copilot AI commented Feb 2, 2026

Malformed RAR archives cause SourceStream.Seek to loop infinitely when attempting to enumerate entries. The loop continues indefinitely because SetStream doesn't advance the stream position but also doesn't signal failure.

Changes

  • SourceStream.cs: Added two safety checks in the Seek method's stream advancement loop:
    1. Throw when SetStream returns false (no more streams available)
    2. Throw when consecutive zero-length streams prevent progress toward target position

Both cases now throw InvalidOperationException with descriptive messages indicating position and failure reason.

Example

var readerOptions = new ReaderOptions { LookForHeader = true };
using var fileStream = File.Open("malformed.rar", FileMode.Open);
using var archive = RarArchive.Open(fileStream, readerOptions);

// Previously: infinite loop
// Now: InvalidOperationException("Cannot seek to position X. End of stream reached at position Y.")
foreach (var entry in archive.Entries) { }

Test case added using actual 512-byte malformed RAR file from issue report.

Original prompt

This section details on the original issue you should resolve

<issue_title>Attempting to count entries in potentially-malformed RAR archive results in infinite loop</issue_title>
<issue_description>See Nanook/GrindCore.SharpCompress#20 for further information. I tested on the latest nuget package (currently 0.45.0-beta.263 ), as well as the latest commit (currently f64fa53 ).

Tl;dr, attempting to count entries on a likely-malformed 512 byte RAR archive ( Dreamfall_Patch.exe-embedded_resource_0 (HIDDEN RESOURCE).rar.zip ) causes an infinite loop in sharpcompress. This issue is specifically about it causing an infinite loop, instead of bailing out with an error or something similar.

The infinite loop happens because this specific set of functions in SourceStream result in an infinite loop when provided a null/broken stream, as they don't ever increment.

SetStream(0);
while (_prevSize + Current.Length < pos)
{
_prevSize += Current.Length;
SetStream(_stream + 1);
}

public bool SetStream(int idx) //allow caller to switch part in multipart
{
if (LoadStream(idx))
{
_stream = idx;
}
return _stream == idx;
}

Example code to reproduce this (obviously, change the file path as needed on your end):

using SharpCompress.Archives;
using SharpCompress.Archives.Rar;
using SharpCompress.Readers;

var readerOptions = new ReaderOptions() { LookForHeader = true };
using (var fileStream =
       File.Open("/home/bestest/investigate_solid/Dreamfall_Patch.exe-embedded_resource_0 (HIDDEN RESOURCE).rar",
           FileMode.Open))
{
    int counter = 0;
    IRarArchive rarFile = RarArchive.OpenArchive(fileStream, readerOptions);
    using (IArchive archive = rarFile) //handles multipart archives
    {
        foreach (IArchiveEntry entry in archive.Entries.Where(e => !e.IsDirectory)) 
            counter++;
    }
    Console.WriteLine(counter);
}

</issue_description>

<agent_instructions>do the same fix as in #1177 but this time the base branch is different</agent_instructions>

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.

Copilot AI and others added 2 commits February 2, 2026 09:31
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix infinite loop when counting entries in malformed RAR archive Fix infinite loop in SourceStream.Seek for malformed archives Feb 2, 2026
Copilot AI requested a review from adamhathcock February 2, 2026 09:40
@adamhathcock adamhathcock marked this pull request as ready for review February 2, 2026 09:45
@kilo-code-bot
Copy link
Contributor

kilo-code-bot bot commented Feb 2, 2026

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Files Reviewed (3 files)
  • src/SharpCompress/IO/SourceStream.cs - 0 issues
  • tests/SharpCompress.Test/Rar/RarArchiveTests.cs - 0 issues
  • tests/TestArchives/Archives/Rar.malformed_512byte.rar - 0 issues

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR hardens SourceStream.Seek to avoid infinite loops when reading malformed RAR archives by detecting non-progressing stream transitions and surfacing them as clear exceptions. It also adds a regression test using the real 512-byte malformed RAR from the linked issue to ensure enumeration now fails fast instead of hanging.

Changes:

  • Updated SourceStream.Seek to:
    • Throw InvalidOperationException when SetStream indicates there are no more streams available before reaching the requested position.
    • Detect consecutive zero-length streams that would prevent forward progress and throw a descriptive InvalidOperationException.
  • Added a RAR archive test Rar_MalformedArchive_NoInfiniteLoop that opens the malformed 512-byte RAR with LookForHeader = true and asserts an InvalidOperationException is thrown when enumerating entries, verifying the exception message contains "Cannot seek to position".
  • Added the Rar.malformed_512byte.rar test fixture under tests/TestArchives/Archives to reproduce and lock in behavior for the reported issue.

Reviewed changes

Copilot reviewed 2 out of 3 changed files in this pull request and generated 1 comment.

File Description
src/SharpCompress/IO/SourceStream.cs Adjusts Seek’s loop over internal streams to throw on end-of-stream and consecutive zero-length streams, preventing the infinite loop when seeking into malformed archives.
tests/SharpCompress.Test/Rar/RarArchiveTests.cs Adds a focused regression test that opens the malformed RAR with ReaderOptions.LookForHeader = true and asserts a non-hanging InvalidOperationException with a seek-related message.
tests/TestArchives/Archives/Rar.malformed_512byte.rar Introduces the malformed 512-byte RAR fixture used by the new regression test to reproduce the prior infinite-loop condition.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

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.

3 participants