From 3ef9c1997ed7f17c6e93ba8eb8ac578acb8fd102 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 22 Jul 2026 12:11:03 +0000 Subject: [PATCH 1/3] Initial plan From 6d6162f72c7daa2b1d514f5e95e487fde76364b9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 22 Jul 2026 12:16:30 +0000 Subject: [PATCH 2/3] fix: prevent pointer-wrap and oversized-length OOB in WebSocket parser MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - websocket_parser.c s_length: reject 64-bit payload lengths with MSB set per RFC 6455 §5.2 before the frame is accepted, preventing integer-wrap on the subsequent pointer check - websocket_parser.c s_body: replace `p + parser->require <= end` (pointer-arithmetic wrap on huge require) with the size_t-safe `parser->require <= (size_t)(end - p)` - WebSocketParser.cpp on_frame_header: change `int length` to `size_t length` to eliminate the size_t→int truncation; return 1 (stops parsing) for any frame whose declared length exceeds MAX_PAYLOAD_LENGTH (16 MB), so on_frame_body is never reached with an attacker-controlled oversized length Closes #852 --- http/WebSocketParser.cpp | 7 +++++-- http/websocket_parser.c | 8 +++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/http/WebSocketParser.cpp b/http/WebSocketParser.cpp index e655a56c6..63e094574 100644 --- a/http/WebSocketParser.cpp +++ b/http/WebSocketParser.cpp @@ -12,8 +12,11 @@ static int on_frame_header(websocket_parser* parser) { if (opcode != WS_OP_CONTINUE) { wp->opcode = opcode; } - int length = parser->length; - int reserve_length = MIN(length + 1, MAX_PAYLOAD_LENGTH); + size_t length = parser->length; + if (length > (size_t)MAX_PAYLOAD_LENGTH) { + return 1; // reject oversized frames; stops parsing before s_body is entered + } + size_t reserve_length = length + 1; if (reserve_length > wp->message.capacity()) { wp->message.reserve(reserve_length); } diff --git a/http/websocket_parser.c b/http/websocket_parser.c index c6f5670d7..af5eaf86c 100644 --- a/http/websocket_parser.c +++ b/http/websocket_parser.c @@ -107,6 +107,12 @@ size_t websocket_parser_execute(websocket_parser *parser, const websocket_parser } p--; if(!parser->require) { + /* RFC 6455 §5.2: the most significant bit of the 64-bit payload + * length MUST be 0. Reject frames that violate this to prevent + * integer-wrap exploits on the pointer check below. */ + if (parser->length & ~((size_t)~(size_t)0 >> 1)) { + return GET_NPARSED(); + } if (parser->flags & WS_HAS_MASK) { SET_STATE(s_mask); parser->require = 4; @@ -142,7 +148,7 @@ size_t websocket_parser_execute(websocket_parser *parser, const websocket_parser break; case s_body: if(parser->require) { - if(p + parser->require <= end) { + if(parser->require <= (size_t)(end - p)) { EMIT_DATA_CB(frame_body, p, parser->require); p += parser->require; parser->require = 0; From 3fc6f84de9473a307acce96e374dd3cbe71e24d3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 22 Jul 2026 12:20:25 +0000 Subject: [PATCH 3/3] fix: improve readability of MSB check and clarify overflow safety --- http/WebSocketParser.cpp | 2 +- http/websocket_parser.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/http/WebSocketParser.cpp b/http/WebSocketParser.cpp index 63e094574..c2c9ebbde 100644 --- a/http/WebSocketParser.cpp +++ b/http/WebSocketParser.cpp @@ -16,7 +16,7 @@ static int on_frame_header(websocket_parser* parser) { if (length > (size_t)MAX_PAYLOAD_LENGTH) { return 1; // reject oversized frames; stops parsing before s_body is entered } - size_t reserve_length = length + 1; + size_t reserve_length = length + 1; // safe: length <= MAX_PAYLOAD_LENGTH (16M) so no overflow if (reserve_length > wp->message.capacity()) { wp->message.reserve(reserve_length); } diff --git a/http/websocket_parser.c b/http/websocket_parser.c index af5eaf86c..6ba50d0b0 100644 --- a/http/websocket_parser.c +++ b/http/websocket_parser.c @@ -110,7 +110,7 @@ size_t websocket_parser_execute(websocket_parser *parser, const websocket_parser /* RFC 6455 §5.2: the most significant bit of the 64-bit payload * length MUST be 0. Reject frames that violate this to prevent * integer-wrap exploits on the pointer check below. */ - if (parser->length & ~((size_t)~(size_t)0 >> 1)) { + if (parser->length > ((size_t)~(size_t)0 >> 1)) { return GET_NPARSED(); } if (parser->flags & WS_HAS_MASK) {