From bfe6764df08802fbf00b7d845421d8ea27484f91 Mon Sep 17 00:00:00 2001 From: nashit hayyat Date: Mon, 20 Jul 2026 15:13:07 +0530 Subject: [PATCH 1/2] inspector: fix out-of-bounds read in ws frame decoding Signed-off-by: nashit hayyat --- src/inspector_socket.cc | 6 +++++- test/cctest/test_inspector_socket.cc | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/inspector_socket.cc b/src/inspector_socket.cc index 52e53373c93adc..6b8537cba83452 100644 --- a/src/inspector_socket.cc +++ b/src/inspector_socket.cc @@ -360,7 +360,11 @@ static ws_decode_result decode_frame_hybi17(const std::vector& buffer, } size_t payload_length = static_cast(payload_length64); - if (buffer.size() - kMaskingKeyWidthInBytes < payload_length) + // The masking key and the payload follow the header `it` already walked + // past, so they have to fit in what is left rather than in the whole buffer. + size_t remaining = static_cast(buffer.end() - it); + if (remaining < kMaskingKeyWidthInBytes || + remaining - kMaskingKeyWidthInBytes < payload_length) return FRAME_INCOMPLETE; std::vector::const_iterator masking_key = it; diff --git a/test/cctest/test_inspector_socket.cc b/test/cctest/test_inspector_socket.cc index 2efa0d55d748f1..8af925f1c9b5e9 100644 --- a/test/cctest/test_inspector_socket.cc +++ b/test/cctest/test_inspector_socket.cc @@ -409,6 +409,24 @@ TEST_F(InspectorSocketTest, ReadsAndWritesInspectorMessage) { reinterpret_cast(&client_socket))); } +TEST_F(InspectorSocketTest, WaitsForFrameBodyToArrive) { + do_write(const_cast(HANDSHAKE_REQ), sizeof(HANDSHAKE_REQ) - 1); + expect_handshake(); + + // A header announcing a masked five byte payload, with the masking key and + // the payload still on the wire. The frame has to be treated as incomplete + // until the remaining bytes show up. + const char FRAME_HEADER[] = {'\x81', '\x85'}; + do_write(FRAME_HEADER, sizeof(FRAME_HEADER)); + + const char FRAME_BODY[] = {'\x01', '\x02', '\x03', '\x04', + '\x69', '\x67', '\x6F', '\x68', '\x6E'}; + do_write(FRAME_BODY, sizeof(FRAME_BODY)); + + const char CLIENT_MESSAGE[] = "hello"; + delegate->ExpectData(CLIENT_MESSAGE, sizeof(CLIENT_MESSAGE) - 1); +} + TEST_F(InspectorSocketTest, BufferEdgeCases) { do_write(const_cast(HANDSHAKE_REQ), sizeof(HANDSHAKE_REQ) - 1); expect_handshake(); From 1958e124eeb2191e73ef57748785fd350028ff76 Mon Sep 17 00:00:00 2001 From: nashit hayyat Date: Wed, 22 Jul 2026 10:18:56 +0530 Subject: [PATCH 2/2] inspector: simplify ws length guard, make test fail without fix Signed-off-by: nashit hayyat --- src/inspector_socket.cc | 3 +-- test/cctest/test_inspector_socket.cc | 7 +++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/inspector_socket.cc b/src/inspector_socket.cc index 6b8537cba83452..970df7cd8db871 100644 --- a/src/inspector_socket.cc +++ b/src/inspector_socket.cc @@ -363,8 +363,7 @@ static ws_decode_result decode_frame_hybi17(const std::vector& buffer, // The masking key and the payload follow the header `it` already walked // past, so they have to fit in what is left rather than in the whole buffer. size_t remaining = static_cast(buffer.end() - it); - if (remaining < kMaskingKeyWidthInBytes || - remaining - kMaskingKeyWidthInBytes < payload_length) + if (remaining < kMaskingKeyWidthInBytes + payload_length) return FRAME_INCOMPLETE; std::vector::const_iterator masking_key = it; diff --git a/test/cctest/test_inspector_socket.cc b/test/cctest/test_inspector_socket.cc index 8af925f1c9b5e9..9282eb4712ff32 100644 --- a/test/cctest/test_inspector_socket.cc +++ b/test/cctest/test_inspector_socket.cc @@ -419,6 +419,13 @@ TEST_F(InspectorSocketTest, WaitsForFrameBodyToArrive) { const char FRAME_HEADER[] = {'\x81', '\x85'}; do_write(FRAME_HEADER, sizeof(FRAME_HEADER)); + // Round trip through the server so the header is guaranteed to have been + // read on its own, instead of arriving together with the body below. + const char SERVER_MESSAGE[] = "ping"; + const char SERVER_FRAME[] = {'\x81', '\x04', 'p', 'i', 'n', 'g'}; + delegate->Write(SERVER_MESSAGE, sizeof(SERVER_MESSAGE) - 1); + expect_on_client(SERVER_FRAME, sizeof(SERVER_FRAME)); + const char FRAME_BODY[] = {'\x01', '\x02', '\x03', '\x04', '\x69', '\x67', '\x6F', '\x68', '\x6E'}; do_write(FRAME_BODY, sizeof(FRAME_BODY));