SharpCompressStream.StackSeek fails to update buffer content when rewinding #722

Closed
opened 2026-01-29 22:16:24 +00:00 by claunia · 2 comments
Owner

Originally created by @IDXGI on GitHub (Nov 19, 2025).

I discovered this issue while investigating #1021.

Observation

It appears that SharpCompressStream uses a buffering design where it loads chunks of 65,536 bytes from the underlying stream. This buffer acts like a sliding window that moves forward as the reading position advances.

The Issue

In TarFactory.TryOpenReader(), the code calls:

((IStreamStack)rewindableStream).StackSeek(pos);

I noticed that StackSeek only updates SharpCompressStream._bufferPosition and SharpCompressStream._internalPosition:

  • _internalPosition: The global position within the entire stream.
  • _bufferPosition: The offset within the current 64KB buffer.

The Logic Flaw

When _internalPosition is modified (specifically when seeking backward/rewinding), the internal buffer logic does not check if the new position is actually within the currently loaded buffer window. It assumes the data is there. If the buffer isn't reloaded or "slid" to match the new _internalPosition, the stream returns incorrect data.

Image

For example, if you attempt to seek back to read the first 6 bytes of the stream, but the buffer is currently holding data from the end of the stream, Read() will return data from the wrong offset.

Impact on #1021

This is the root cause of the "Stream Corruption" reported in #1021:

  1. Due to an incorrect size calculation, the reader read all the way to the end of the stream.
  2. This caused the 64KB buffer window to slide to the very end of the stream.
  3. When the code attempted to reset _internalPosition to 0 to try a different TAR parsing logic, the buffer content was not refreshed.
  4. The buffer still contained data from the end of the stream, causing the LZIP header check to fail (as it was reading garbage data instead of the file header).

This issue seems to be isolated to SharpCompressStream and is not directly related to the Tar implementation. It likely went unnoticed until now because format identification usually happens within the first 65,536 bytes, so the buffer window rarely needs to move and then reset in this manner.

Originally created by @IDXGI on GitHub (Nov 19, 2025). I discovered this issue while investigating #1021. ### Observation It appears that `SharpCompressStream` uses a buffering design where it loads chunks of 65,536 bytes from the underlying stream. This buffer acts like a sliding window that moves forward as the reading position advances. ### The Issue In `TarFactory.TryOpenReader()`, the code calls: ```csharp ((IStreamStack)rewindableStream).StackSeek(pos); ``` I noticed that `StackSeek` only updates `SharpCompressStream._bufferPosition` and `SharpCompressStream._internalPosition`: * `_internalPosition`: The global position within the entire stream. * `_bufferPosition`: The offset within the current 64KB buffer. ### The Logic Flaw When `_internalPosition` is modified (specifically when seeking backward/rewinding), the internal buffer logic does not check if the new position is actually within the currently loaded buffer window. It assumes the data is there. If the buffer isn't reloaded or "slid" to match the new `_internalPosition`, the stream returns incorrect data. <img width="509" height="284" alt="Image" src="https://github.com/user-attachments/assets/6c8a5fe9-c188-430a-b21c-a9d2b51346c7" /> For example, if you attempt to seek back to read the first 6 bytes of the stream, but the buffer is currently holding data from the end of the stream, `Read()` will return data from the wrong offset. ### Impact on #1021 This is the root cause of the "Stream Corruption" reported in #1021: 1. Due to an incorrect size calculation, the reader read all the way to the end of the stream. 2. This caused the 64KB buffer window to slide to the very end of the stream. 3. When the code attempted to reset `_internalPosition` to `0` to try a different TAR parsing logic, the buffer content was **not** refreshed. 4. The buffer still contained data from the end of the stream, causing the LZIP header check to fail (as it was reading garbage data instead of the file header). This issue seems to be isolated to `SharpCompressStream` and is not directly related to the Tar implementation. It likely went unnoticed until now because format identification usually happens within the first 65,536 bytes, so the buffer window rarely needs to move and then reset in this manner.
Author
Owner

@Morilli commented on GitHub (Nov 20, 2025):

Should have been resolved by #1017.

@Morilli commented on GitHub (Nov 20, 2025): Should have been resolved by #1017.
Author
Owner

@IDXGI commented on GitHub (Nov 22, 2025):

Thanks @Morilli, I'll trust that #1017 fixes the buffer update logic. Closing this issue.

@IDXGI commented on GitHub (Nov 22, 2025): Thanks @Morilli, I'll trust that #1017 fixes the buffer update logic. Closing this issue.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/sharpcompress#722