fix(websocket): OOB read from oversized/wrapped frame length (#852) - #864
Merged
Conversation
…852) The vendored websocket_parser.c body-availability check used 'p + parser->require <= end'. For a peer-declared 64-bit payload length (e.g. all 0xFF, MSB set which RFC 6455 forbids), that pointer arithmetic overflows and wraps below 'end', so the check passes and frame_body is emitted with length ~= SIZE_MAX while only a few bytes are valid. The C++ wrapper then append()s / in-place decode()s that many bytes -> OOB read / crash for any peer that can send WebSocket frames. - websocket_parser.c: compare against real remaining bytes, 'parser->require <= (size_t)(end - p)', which cannot overflow. - WebSocketParser.cpp on_frame_header: stop truncating parser->length to int; use it only as a capacity hint capped to MAX_PAYLOAD_LENGTH (never trust a peer-declared length for allocation). Verified: a crafted 0xFF-length frame now emits body length=1 (the real available byte) instead of 0xFFFFFFFFFFFFFFFF; normal frames (unmasked, split across execute() calls, 16-bit length) still parse correctly. Fixes #852.
ithewei
force-pushed
the
fix/websocket-parser-oob
branch
from
August 6, 2026 03:13
2e127db to
967cdf6
Compare
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.
Fixes #852 — OOB read from an oversized / wrapped WebSocket frame length.
Root cause
http/websocket_parser.c(vendored) checked body availability with:For a peer-declared 64-bit payload length (e.g. all
0xFF, which also has the MSB set that RFC 6455 §5.2 forbids),parser->requireis ~SIZE_MAX, sop + parser->requireoverflows the pointer and wraps to a value ≤end. The check passes andframe_bodyis emitted withlength ≈ SIZE_MAXwhile only a few bytes are valid.WebSocketParser.cppthen trusts it:→ out-of-bounds read / crash for any peer that can send WebSocket frames.
Fix
websocket_parser.c: compare against the real remaining bytes,parser->require <= (size_t)(end - p), which cannot overflow.WebSocketParser.cppon_frame_header: stop truncatingparser->length(size_t) toint; use it only as a capacity hint capped toMAX_PAYLOAD_LENGTH— never trust a peer-declared length for allocation. (Body bytes are still appended incrementally against real buffer data.)Verified
81 7F FF FF FF FF FF FF FF FF 41(FIN+TEXT, 64-bit len all0xFF, 1 payload byte):on_frame_body length=18446744073709551615on_frame_body length=1execute()calls, and a 126/16-bit-length 200-byte frame — all OK.make libhv+ ws client/server examples build clean.Reported by the issue author (with a minimal C-core repro); this patches the vendored parser and the product-specific amplification in the C++ wrapper.