mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-02-09 05:24:55 +00:00
Regression: ZIP parsing fails depending on Stream.Read chunking on non-seekable streams #771
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @rleroux-regnology on GitHub (Jan 27, 2026).
Originally assigned to: @adamhathcock, @Copilot on GitHub.
Hi,
I’m hitting what looks like a stream chunking sensitivity regression when reading ZIP archives from a non-seekable stream. With the exact same ZIP bytes, SharpCompress will sometimes fail depending only on how the underlying
Stream.Read()splits the data.Regression note
The exact same code path works correctly with SharpCompress 0.40.0.
The failure (
ZlibExceptionin the chunked case) starts occurring in newer versions.Context / real-world scenario
This happens in a real ASP.NET Core streaming pipeline (multipart/form-data):
HttpRequest.BodyMultipartReader(multipart/form-data)ReaderFactory.Open(...).MoveToNextEntry()A seemingly unrelated change (for example changing a text field value from
"my-value"to"my-valu") shifts the alignment of the ZIP part by 1 byte, which changes the short-read pattern seen by SharpCompress and triggers a failure.To make this report independent of ASP.NET / multipart, the repro below uses a custom non-seekable stream that returns legal short reads.
Reproduction
This snippet (with stream.zip) reads the same ZIP bytes three ways:
MemoryStreamOnly case (3) fails with a
ZlibException. Wrapping the stream with a simple coalescing wrapper fixes the issue.Observed behavior
Baseline (MemoryStream)works.Chunked(first=3816, then=4096)works.Chunked(first=3815, then=4096)throwZlibException.FillReadStreammakes it behave like baseline againThe only difference between the failing and non-failing cases is one byte in the first
Read()result.Why this is problematic
From a consumer point of view:
Streambehavior.Currently, SharpCompress becomes sensitive to buffer alignment and short-read patterns, which makes it unreliable in legitimate streaming scenarios.
Expected behavior / suggestion
SharpCompress should not assume that
Read()will return “enough” bytes in a single call.With identical input bytes, parsing should be deterministic regardless of legal short-read patterns.
Workaround on consumer side
Wrapping the input stream with a simple coalescing stream (like
FillReadStream) fixes the issue, but this should not be required for valid non-seekable inputs.Summary
ZlibException.Read()semantics.@adamhathcock commented on GitHub (Jan 27, 2026):
I think the linked PR covers this. If I'm understanding, a shorter read than requested blows up the parsing. The new code takes that into account.
https://github.com/adamhathcock/sharpcompress/pull/1169
@adamhathcock commented on GitHub (Jan 28, 2026):
One of the latest betas should have this fix https://www.nuget.org/packages/SharpCompress/0.44.5-beta.27
@rleroux-regnology commented on GitHub (Jan 29, 2026):
Works perfectly in 0.44.5, thank you very much for your responsiveness on the various fixes ❤