diff --git a/easywsclient.cpp b/easywsclient.cpp index 8f8f4be..0770870 100644 --- a/easywsclient.cpp +++ b/easywsclient.cpp @@ -172,8 +172,13 @@ class _RealWebSocket : public easywsclient::WebSocket socket_t sockfd; readyStateValues readyState; bool useMask; + bool isRxBad; - _RealWebSocket(socket_t sockfd, bool useMask) : sockfd(sockfd), readyState(OPEN), useMask(useMask) { + _RealWebSocket(socket_t sockfd, bool useMask) + : sockfd(sockfd) + , readyState(OPEN) + , useMask(useMask) + , isRxBad(false) { } readyStateValues getReadyState() const { @@ -264,6 +269,9 @@ class _RealWebSocket : public easywsclient::WebSocket virtual void _dispatchBinary(BytesCallback_Imp & callable) { // TODO: consider acquiring a lock on rxbuf... + if (isRxBad) { + return; + } while (true) { wsheader_type ws; if (rxbuf.size() < 2) { return; /* Need at least 2 */ } @@ -296,6 +304,20 @@ class _RealWebSocket : public easywsclient::WebSocket ws.N |= ((uint64_t) data[8]) << 8; ws.N |= ((uint64_t) data[9]) << 0; i = 10; + if (ws.N & 0x8000000000000000ull) { + // https://tools.ietf.org/html/rfc6455 writes the "the most + // significant bit MUST be 0." + // + // We can't drop the frame, because (1) we don't we don't + // know how much data to skip over to find the next header, + // and (2) this would be an impractically long length, even + // if it were valid. So just close() and return immediately + // for now. + isRxBad = true; + fprintf(stderr, "ERROR: Frame has invalid frame length. Closing.\n"); + close(); + return; + } } if (ws.mask) { ws.masking_key[0] = ((uint8_t) data[i+0]) << 0; @@ -309,6 +331,9 @@ class _RealWebSocket : public easywsclient::WebSocket ws.masking_key[2] = 0; ws.masking_key[3] = 0; } + + // Note: The checks above should hopefully ensure this addition + // cannot overflow: if (rxbuf.size() < ws.header_size+ws.N) { return; /* Need: ws.header_size+ws.N - rxbuf.size() */ } // We got a whole message, now do something with it: