Repository navigation
Conversation
In this commit, we add an incremental decoder that checks a frame's declared payload length before retaining or unmasking its body. Fragment state survives input boundaries and counts toward one message budget, including when control frames interrupt it. The decoder returns one completed message and unconsumed input instead of collecting an arbitrary batch. Compression is refused before inflation; the existing decoder remains unchanged for existing callers. Tests cover incomplete oversized headers, exact extended-length boundaries, fragmentation across chunks, control frames, and every split of a masked message.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
In this PR, we add an opt-in incremental WebSocket decoder that checks a frame's declared payload length before retaining or unmasking its body. A peer can advertise an oversized payload and then stop sending, so an application-level check after decoding cannot enforce this bound.
The decoder carries fragmented-message state across input boundaries and counts continuation payloads against one message limit, including when control frames interrupt the message. It returns one completed frame or message together with the unconsumed input. Compression is rejected before inflation.
Both limits are caller-configured and must be positive. The existing decoder API remains unchanged, and no Erlang code is added. These are per-connection input bounds, not limits on connection count, socket output, or application-retained data. Broader protocol validation retains the existing behavior.
We built this for a long-lived daemon hosting multiple agent sessions, where checking a completed application message is too late to bound parser memory. Mist #92 exposes the opt-in decoder through its upgrade API. We have merged the change into our fork for that integration and are offering it here for consideration; upstream acceptance is not a prerequisite for our deployment.
All 18 tests pass locally under a 120-second outer deadline. Coverage includes incomplete oversized headers, exact extended-length boundaries, cumulative fragments across TCP reads, interleaved control frames, compressed input, and every byte split of a masked message. An isolated negative control that raises both configured limits fails four assertions, including rejection before a payload arrives. Independent review found no blocking regression.