Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 20 additions & 2 deletions src/SharpCompress/IO/SourceStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -222,8 +222,26 @@ public override long Seek(long offset, SeekOrigin origin)
SetStream(0);
while (_prevSize + Current.Length < pos)
{
_prevSize += Current.Length;
SetStream(_stream + 1);
var currentLength = Current.Length;
_prevSize += currentLength;

if (!SetStream(_stream + 1))
{
// No more streams available, cannot seek to requested position
throw new InvalidOperationException(
$"Cannot seek to position {pos}. End of stream reached at position {_prevSize}."
);
}

// Safety check: if we have a zero-length stream and we're still not
// making progress toward the target position, we're in an invalid state
if (currentLength == 0 && Current.Length == 0)
{
// Both old and new stream have zero length - cannot make progress
throw new InvalidOperationException(
$"Cannot seek to position {pos}. Encountered zero-length streams at position {_prevSize}."
);
}
}
}

Expand Down
33 changes: 33 additions & 0 deletions tests/SharpCompress.Test/Rar/RarArchiveTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -717,4 +717,37 @@ public void Rar_StreamValidation_ThrowsOnTruncatedStream()
// Verify the exception message matches our expectation
Assert.Contains("unpacked file size does not match header", exception.Message);
}

/// <summary>
/// Test case for malformed RAR archives that previously caused infinite loops.
/// This test verifies that attempting to read entries from a potentially malformed
/// 512-byte RAR archive throws an InvalidOperationException instead of looping infinitely.
/// See: https://github.com/adamhathcock/sharpcompress/issues/1176
/// </summary>
[Fact]
public void Rar_MalformedArchive_NoInfiniteLoop()
{
var testFile = "Rar.malformed_512byte.rar";
var readerOptions = new ReaderOptions { LookForHeader = true };

// This should throw InvalidOperationException, not hang in an infinite loop
var exception = Assert.Throws<InvalidOperationException>(() =>
{
using var fileStream = File.Open(
Path.Combine(TEST_ARCHIVES_PATH, testFile),
FileMode.Open
);
using var archive = RarArchive.Open(fileStream, readerOptions);

// Attempting to enumerate entries should throw an exception
// instead of looping infinitely
foreach (var entry in archive.Entries.Where(e => !e.IsDirectory))
{
// This line should not be reached due to the exception
}
});

// Verify that the exception is related to seeking beyond available data
Assert.Contains("Cannot seek to position", exception.Message);
}
}
Binary file not shown.
Loading