Raise a catchable error on malformed Huffman-coded input - #26
Merged
whatyouhide merged 1 commit intoJul 25, 2026
Merged
Conversation
HPAX.Huffman.decode/1 only handled two "end of input" cases: an
exhausted binary, and 1-7 leftover bits that form valid EOS padding.
Any input that leaves 8 or more trailing bits which don't correspond
to a complete Huffman code - which can only happen with a malformed
or malicious encoding, since a real encoder never produces such
output - matched no clause at all, raising an unhandled
FunctionClauseError instead of the {:hpax, _} throw that callers of
HPAX.decode/2 already know how to handle gracefully.
A peer can trigger this by sending a HEADERS frame with a
deliberately invalid Huffman-coded string value, crashing the
decoding process instead of the connection being cleanly failed per
RFC 7541.
mtrudel
marked this pull request as draft
July 25, 2026 02:14
Contributor
Author
|
Ignore for now - Claude went rogue when I was tracking down some intermittent Huffman decoding issues and started cutting PRs. This will likely end up being a bonafide PR but it needs a human pass before consideration |
Contributor
|
LOL been there |
mtrudel
force-pushed
the
fix/huffman-decode-invalid-encoding
branch
from
July 25, 2026 18:54
18a42a5 to
7719986
Compare
mtrudel
marked this pull request as ready for review
July 25, 2026 18:57
Contributor
Author
|
This stands ready for review |
4 tasks
Contributor
|
Lovely, thank you @mtrudel! 🫶 |
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.
Summary
HPAX.Huffman.decode/1only has clauses for two "end of input" cases: an exhausted binary, and 1-7 leftover bits that form valid EOS padding. Any input that leaves 8 or more trailing bits which don't correspond to a complete Huffman code matches no clause at all, raising an unhandledFunctionClauseErrorinstead of the{:hpax, _}throw that callers ofHPAX.decode/2already know how to catch and turn into a graceful{:error, _}:This can only happen with a malformed/malicious encoding (a real encoder never produces output with more than 7 trailing bits that aren't a complete code), but a peer can trivially trigger it by sending a deliberately invalid Huffman-coded string. We hit this via an intermittent crash in Bandit's h2spec CI.
Fix
Add a final catch-all
decode/1clause that throws the same{:hpax, {:protocol_error, :invalid_huffman_encoding}}the existing padding-mismatch case already throws.Test plan
Huffman.decode/1throws the catchable:hpaxerror (rather than crashing) for several malformed inputs