diff --git a/src/SharpCompress/IO/SourceStream.cs b/src/SharpCompress/IO/SourceStream.cs
index 0712d915c..606b0fa75 100644
--- a/src/SharpCompress/IO/SourceStream.cs
+++ b/src/SharpCompress/IO/SourceStream.cs
@@ -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}."
+ );
+ }
}
}
diff --git a/tests/SharpCompress.Test/Rar/RarArchiveTests.cs b/tests/SharpCompress.Test/Rar/RarArchiveTests.cs
index ba42f649c..7b6a94b2d 100644
--- a/tests/SharpCompress.Test/Rar/RarArchiveTests.cs
+++ b/tests/SharpCompress.Test/Rar/RarArchiveTests.cs
@@ -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);
}
+
+ ///
+ /// 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
+ ///
+ [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(() =>
+ {
+ 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);
+ }
}
diff --git a/tests/TestArchives/Archives/Rar.malformed_512byte.rar b/tests/TestArchives/Archives/Rar.malformed_512byte.rar
new file mode 100644
index 000000000..914693f88
Binary files /dev/null and b/tests/TestArchives/Archives/Rar.malformed_512byte.rar differ