Skip to content

[release/11.0] Fix DeflateEncoder.GetMaxCompressedLength conservative bound - #132389

Open
BrzVlad wants to merge 1 commit into
dotnet:release/11.0from
BrzVlad:backport-zlib-compression
Open

[release/11.0] Fix DeflateEncoder.GetMaxCompressedLength conservative bound#132389
BrzVlad wants to merge 1 commit into
dotnet:release/11.0from
BrzVlad:backport-zlib-compression

Conversation

@BrzVlad

@BrzVlad BrzVlad commented Aug 17, 2026

Copy link
Copy Markdown
Member

Previous code was using the implementation from compressBound(). This api returns a conservative bound when using the compress() APIs, which our .NET implementation doesn't use (it uses deflate directly). The compress API does a deflate with default configuration, while our API allows custom configuration (via the quality level, window size and a few others). This means that the compressBound is not valid when using the deflate API with custom parameters.

zlib exposes the deflateBound method which can be used to obtain a conservative size. The problem with this API is that it requires to know the parameters of the compression, which we don't have available in our .NET API, given GetMaxCompressedLenght is static, applying universally to all compressions. While it is not yet decided if we will add a new API to support obtaining the bound from the library, this commit adds a workaround, by computing the maximum bound for every compression configuration exposed by our .NET APIs

The formula is obtained from our zlib-ng sources in deflate.c. Mobile uses zlib however. Validated that this change works correctly on maccatalyst, ios simulator and that the current logic stands with the current open source code for zlib (which applies to android). The actual bound used by Apple and Android can always change, so we do have a small risk that our hardcoded limit will diverge. I believe the only safe solution for this would be to make use of the actual deflateBound method, which requires adjustement to our API.

Fixes issue with new .NET11 APIs (#127563). Backport of #132274

Previous code was using the implementation from compressBound(). This api returns a conservative bound when using the compress() APIs, which our .NET implementation doesn't use (it uses deflate directly). The compress API does a deflate with default configuration, while our API allows custom configuration (via the quality level, window size and a few others). This means that the compressBound is not valid when using the deflate API with custom parameters.

zlib exposes the deflateBound method which can be used to obtain a conservative size. The problem with this API is that it requires to know the parameters of the compression, which we don't have available in our .NET API, given GetMaxCompressedLenght is static, applying universally to all compressions. While it is not yet decided if we will add a new API to support obtaining the bound from the library, this commit adds a workaround, by computing the maximum bound for every compression configuration exposed by our .NET APIs

The formula is obtained from our zlib-ng sources in deflate.c. Mobile uses zlib however. Validated that this change works correctly on maccatalyst, ios simulator and that the current logic stands with the current open source code for zlib (which applies to android). The actual bound used by Apple and Android can always change, so we do have a small risk that our hardcoded limit will diverge. I believe the only safe solution for this would be to make use of the actual deflateBound method, which requires adjustement to our API.
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
13 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @karelz, @dotnet/area-system-io-compression
See info in area-owners.md if you want to be subscribed.

@BrzVlad

BrzVlad commented Aug 17, 2026

Copy link
Copy Markdown
Member Author

@steveisok Is this the right way to backport for RC1 ? without any tactics approval ? I see release/11.0 and release/11.0-rc1 are currently identical, so I'm assuming rc1 branch will move forward later today ?

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the conservative upper-bound calculation used by DeflateEncoder.GetMaxCompressedLength, and adjusts related encoder comments/tests to reflect the new sizing behavior, with the goal of preventing DestinationTooSmall failures (notably on mobile platforms) when callers allocate buffers based on GetMaxCompressedLength.

Changes:

  • Replaces the previous compressBound()-based sizing behavior in DeflateEncoder.GetMaxCompressedLength with a managed bound derived from deflateBound()-style worst-case formulas.
  • Updates ZLibEncoder / GZipEncoder comments to align with the new bound semantics.
  • Re-enables the “all window logs” roundtrip test on mobile by removing the [ActiveIssue] skip.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateEncoder.cs Changes max-compressed-length computation to a managed conservative bound.
src/libraries/System.IO.Compression/src/System/IO/Compression/GZipEncoder.cs Updates documentation/comments to reflect new bound source/overhead.
src/libraries/System.IO.Compression/src/System/IO/Compression/ZLibEncoder.cs Updates documentation/comments to reflect new bound semantics.
src/libraries/Common/tests/System/IO/Compression/EncoderDecoderTestBase.cs Removes mobile skip so the window-log coverage test runs on those platforms.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants