From 97f58b412eb919738097ccdf87595b9f3679bdd9 Mon Sep 17 00:00:00 2001 From: Morilli <35152647+Morilli@users.noreply.github.com> Date: Fri, 14 Nov 2025 03:36:52 +0100 Subject: [PATCH 1/4] Add test for StackSeek behavior --- .../Streams/RewindableStreamTest.cs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/SharpCompress.Test/Streams/RewindableStreamTest.cs b/tests/SharpCompress.Test/Streams/RewindableStreamTest.cs index d83ed86c..37580df9 100644 --- a/tests/SharpCompress.Test/Streams/RewindableStreamTest.cs +++ b/tests/SharpCompress.Test/Streams/RewindableStreamTest.cs @@ -85,4 +85,22 @@ public class RewindableStreamTest Assert.Equal(6, br.ReadInt32()); Assert.Equal(7, br.ReadInt32()); } + + [Fact] + public void TestSmallBuffer() + { + var ms = new MemoryStream(); + var testData = new byte[100]; + for (byte i = 0; i < 100; i++) + { + testData[i] = i; + } + ms.Write(testData); + ms.Position = 0; + using var stream = new SharpCompressStream(ms, bufferSize: 64); + var br = new BinaryReader(stream); + stream.StackSeek(100); + stream.StackSeek(10); + Assert.Equal(10, br.ReadByte()); + } } From 9a876abd3103cd84e9f5ea259bb8a2fc924fd43f Mon Sep 17 00:00:00 2001 From: Morilli <35152647+Morilli@users.noreply.github.com> Date: Fri, 14 Nov 2025 01:47:15 +0100 Subject: [PATCH 2/4] fix IStreamStack.StackSeek with buffering streams --- src/SharpCompress/IO/IStreamStack.cs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/SharpCompress/IO/IStreamStack.cs b/src/SharpCompress/IO/IStreamStack.cs index 56c020c8..92bd2e06 100644 --- a/src/SharpCompress/IO/IStreamStack.cs +++ b/src/SharpCompress/IO/IStreamStack.cs @@ -143,7 +143,6 @@ namespace SharpCompress.IO var stack = new List(); Stream? current = stream as Stream; int lastBufferingIndex = -1; - int firstSeekableIndex = -1; Stream? firstSeekableStream = null; // Traverse the stack, collecting info @@ -161,7 +160,6 @@ namespace SharpCompress.IO // Find the first seekable stream (closest to the root) if (current != null && current.CanSeek) { - firstSeekableIndex = stack.Count; firstSeekableStream = current; } @@ -169,16 +167,16 @@ namespace SharpCompress.IO if (lastBufferingIndex != -1) { var bufferingStream = stack[lastBufferingIndex]; - if (position >= 0 && position < bufferingStream.BufferSize) + var targetBufferPosition = position - bufferingStream.GetPosition() + bufferingStream.BufferPosition; + + if (targetBufferPosition >= 0 && targetBufferPosition <= bufferingStream.BufferSize) { - bufferingStream.BufferPosition = (int)position; + bufferingStream.BufferPosition = (int)targetBufferPosition; return position; } - else - { - // If position is not in buffer, reset buffer and proceed as non-buffering - bufferingStream.BufferPosition = 0; - } + + // If position is not in buffer, reset buffer and proceed as non-buffering + bufferingStream.BufferPosition = 0; // Continue to seek as if no buffer is present } From 783521928df435ebcd3c9a6d77be7960e0fdd0ea Mon Sep 17 00:00:00 2001 From: Morilli <35152647+Morilli@users.noreply.github.com> Date: Fri, 14 Nov 2025 01:49:01 +0100 Subject: [PATCH 3/4] fix SharpCompressStream BufferSize setter and Seek as well the BufferSize setter was completely broken and trashed the `_internalPosition` value on set, for `Seek` this is just an off-by-one fix allowing seeking to immediately past the last byte in the buffer --- src/SharpCompress/IO/SharpCompressStream.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/SharpCompress/IO/SharpCompressStream.cs b/src/SharpCompress/IO/SharpCompressStream.cs index 1dadce4e..00c0ada2 100644 --- a/src/SharpCompress/IO/SharpCompressStream.cs +++ b/src/SharpCompress/IO/SharpCompressStream.cs @@ -79,7 +79,7 @@ public class SharpCompressStream : Stream, IStreamStack { if (value < 0 || value > _bufferedLength) throw new ArgumentOutOfRangeException(nameof(value)); - _internalPosition = value; + _internalPosition = _internalPosition - _bufferPosition + value; _bufferPosition = value; ValidateBufferState(); // Add here } @@ -291,7 +291,7 @@ public class SharpCompressStream : Stream, IStreamStack long bufferPos = _internalPosition - _bufferPosition; - if (targetPos >= bufferPos && targetPos < bufferPos + _bufferedLength) + if (targetPos >= bufferPos && targetPos <= bufferPos + _bufferedLength) { _bufferPosition = (int)(targetPos - bufferPos); //repoint within the buffer _internalPosition = targetPos; From e3a25ecdc0867e466cb849e164b79c3c889c4a64 Mon Sep 17 00:00:00 2001 From: Morilli <35152647+Morilli@users.noreply.github.com> Date: Fri, 14 Nov 2025 03:54:26 +0100 Subject: [PATCH 4/4] make formatting worse with csharpier --- src/SharpCompress/IO/IStreamStack.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/SharpCompress/IO/IStreamStack.cs b/src/SharpCompress/IO/IStreamStack.cs index 92bd2e06..943f7c25 100644 --- a/src/SharpCompress/IO/IStreamStack.cs +++ b/src/SharpCompress/IO/IStreamStack.cs @@ -167,7 +167,8 @@ namespace SharpCompress.IO if (lastBufferingIndex != -1) { var bufferingStream = stack[lastBufferingIndex]; - var targetBufferPosition = position - bufferingStream.GetPosition() + bufferingStream.BufferPosition; + var targetBufferPosition = + position - bufferingStream.GetPosition() + bufferingStream.BufferPosition; if (targetBufferPosition >= 0 && targetBufferPosition <= bufferingStream.BufferSize) {