diff --git a/src/inspector_socket.cc b/src/inspector_socket.cc index 52e53373c93adc..970df7cd8db871 100644 --- a/src/inspector_socket.cc +++ b/src/inspector_socket.cc @@ -360,7 +360,10 @@ 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 + 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..9282eb4712ff32 100644 --- a/test/cctest/test_inspector_socket.cc +++ b/test/cctest/test_inspector_socket.cc @@ -409,6 +409,31 @@ 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)); + + // 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)); + + 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();