Summary
libhv vendors http/websocket_parser.c (from the php-ion websocket-parser lineage). The body-length availability check uses pointer arithmetic that can wrap when the 64-bit payload length is extremely large (including values with the high bit set, which RFC 6455 §5.2 forbids).
When wrap occurs, on_frame_body is invoked with length ≈ SIZE_MAX while only a few input bytes are valid. libhv’s C++ wrapper then trusts that length:
// http/WebSocketParser.cpp — on_frame_body
if (wp->parser->flags & WS_HAS_MASK) {
websocket_parser_decode((char*)at, at, length, wp->parser);
}
wp->message.append(at, length);
This is an out-of-bounds read risk (and practical process abort) for any path that feeds attacker-controlled WebSocket frames into WebSocketParser::FeedRecvData.
Additionally, on_frame_header does int length = parser->length;, truncating size_t lengths.
Honesty / related work
The C-level wrap condition was already described for upstream php-ion/websocket-parser in:
I am not claiming first discovery of that C check. This report is about libhv still shipping the vulnerable vendored code and the product-specific amplification in WebSocketParser.cpp (append / in-place websocket_parser_decode on attacker-sized length).
Related but different: #769 (masked decode 1-byte OOB) — closed; this issue is the oversized-length / pointer-wrap class.
Minimal C-core reproduction (vendored parser)
Crafted frame: FIN+text, 64-bit length field all 0xFF, then 1 payload byte A.
Expected: body callback receives length = 0xFFFFFFFFFFFFFFFF (or similarly huge) after the wrap check treats the body as “fully available”.
I verified this against current master http/websocket_parser.c (case s_body: if (p + parser->require <= end)).
Suggested fix
- Reject 64-bit lengths with MSB set (RFC 6455 §5.2).
- Replace pointer compare with a size_t-safe remaining check, e.g.
if (parser->require <= (size_t)(end - p))
- In
WebSocketParser.cpp, re-validate length against remaining buffer before append / decode; avoid casting payload length to int.
Impact
- Attacker model: peer that can send WebSocket binary/text frames (client or server role depending on how libhv is used).
- Effect: out-of-bounds read / crash in process using
WebSocketParser.
- CWE: CWE-190 → CWE-125 (caller trust of length).
Environment
- libhv
master (raw files pulled 2026-07-22)
- Local lab only; no production testing
Thanks for maintaining libhv. Happy to retest a patch.
Summary
libhvvendorshttp/websocket_parser.c(from the php-ion websocket-parser lineage). The body-length availability check uses pointer arithmetic that can wrap when the 64-bit payload length is extremely large (including values with the high bit set, which RFC 6455 §5.2 forbids).When wrap occurs,
on_frame_bodyis invoked withlength ≈ SIZE_MAXwhile only a few input bytes are valid. libhv’s C++ wrapper then trusts that length:This is an out-of-bounds read risk (and practical process abort) for any path that feeds attacker-controlled WebSocket frames into
WebSocketParser::FeedRecvData.Additionally,
on_frame_headerdoesint length = parser->length;, truncatingsize_tlengths.Honesty / related work
The C-level wrap condition was already described for upstream
php-ion/websocket-parserin:I am not claiming first discovery of that C check. This report is about libhv still shipping the vulnerable vendored code and the product-specific amplification in
WebSocketParser.cpp(append/ in-placewebsocket_parser_decodeon attacker-sizedlength).Related but different: #769 (masked decode 1-byte OOB) — closed; this issue is the oversized-length / pointer-wrap class.
Minimal C-core reproduction (vendored parser)
Crafted frame: FIN+text, 64-bit length field all
0xFF, then 1 payload byteA.Expected: body callback receives
length = 0xFFFFFFFFFFFFFFFF(or similarly huge) after the wrap check treats the body as “fully available”.I verified this against current
masterhttp/websocket_parser.c(case s_body:if (p + parser->require <= end)).Suggested fix
if (parser->require <= (size_t)(end - p))WebSocketParser.cpp, re-validatelengthagainst remaining buffer beforeappend/decode; avoid casting payload length toint.Impact
WebSocketParser.Environment
master(raw files pulled 2026-07-22)Thanks for maintaining libhv. Happy to retest a patch.