Decoder's 100 MiB window limit is enforced on reset but not on first use
@lilith is already working on this.
Since Aug 29, 2026.
- Dominant language
- Rust
- Stars
- 2
- Forks
- 0
- PR merge metrics
- No merged PRs in 30d
Description
Summary
MAXIMUM_ALLOWED_WINDOW_SIZE (100 MiB, decoding/frame_decoder.rs:19) is checked in FrameDecoderState::reset but not in FrameDecoderState::new. Whether a frame is accepted therefore depends on whether the FrameDecoder has been used before:
- First use —
FrameDecoder::new()then decode — takes thenewpath, no limit check, andDecoderScratch::new(window_size)sizes the buffer from the header. - Any later use takes
reset, which returnsWindowSizeTooBig.
Measured
On aarch64-apple-darwin, with the encoder temporarily declaring the uncapped window_log 27 for level 22 (128 MiB):
fresh FrameDecoder: L22 declared_window=134217728 ours=ok
reused FrameDecoder: L22 declared_window=134217728 ours=WindowSizeTooBig { requested: 134217728 }
Levels 17-21 (8/32/64 MiB) pass on both paths. The divergence is exactly the 100 MiB limit.
Why it matters
- Inconsistent contract. The same bytes decode or fail depending on decoder reuse, which is not something a caller can reason about.
decoding/streaming_decoder.rs:53documents "the 100 MiB internal window cap" as if it were unconditional. - The unchecked path is the allocating one.
FrameDecoderState::newsizesDecodeBufferfrom an attacker-controlled header field with no ceiling below the format's own (3.75 TB, enforced only byMAX_WINDOW_SIZEinframe.rs). This is a resource-management problem, not a memory-safety one, but a fresh decoder is the common shape for one-shot decode of untrusted input.
Found while
Fixing #9. The window cap chosen there (MAX_ENCODER_WINDOW_LOG = 23, 8 MiB) is partly justified by this limit, so the asymmetry is worth resolving before anyone raises it.
Suggested fix
Move the check into FrameDecoderState::new as well — ideally into frame::read_frame_header's caller path so there is one place. Needs a check that the decode corpus and conformance vectors stay green; nothing in decodecorpus_files/ declares anything near 100 MiB, so the expectation is no test movement.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.