Add a check for invalid frame length. Credit to Dane (4cad@silvertoque).

Closes #85.
This commit is contained in:
David Baird
2019-05-19 10:04:43 -04:00
parent 112cb81567
commit 4b8bead6a1
+26 -1
View File
@@ -172,8 +172,13 @@ class _RealWebSocket : public easywsclient::WebSocket
socket_t sockfd; socket_t sockfd;
readyStateValues readyState; readyStateValues readyState;
bool useMask; 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 { readyStateValues getReadyState() const {
@@ -264,6 +269,9 @@ class _RealWebSocket : public easywsclient::WebSocket
virtual void _dispatchBinary(BytesCallback_Imp & callable) { virtual void _dispatchBinary(BytesCallback_Imp & callable) {
// TODO: consider acquiring a lock on rxbuf... // TODO: consider acquiring a lock on rxbuf...
if (isRxBad) {
return;
}
while (true) { while (true) {
wsheader_type ws; wsheader_type ws;
if (rxbuf.size() < 2) { return; /* Need at least 2 */ } 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[8]) << 8;
ws.N |= ((uint64_t) data[9]) << 0; ws.N |= ((uint64_t) data[9]) << 0;
i = 10; 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) { if (ws.mask) {
ws.masking_key[0] = ((uint8_t) data[i+0]) << 0; 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[2] = 0;
ws.masking_key[3] = 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() */ } 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: // We got a whole message, now do something with it: