From 6a23afe13b22f6b2076c69ffbff033f0dbbcbc81 Mon Sep 17 00:00:00 2001 From: Kurt Pattyn Date: Tue, 27 Aug 2013 23:01:19 +0200 Subject: [PATCH] Added extra checks: - check on minimum representation of frame length (according RFC 6455 para 5.2) - extra checks on network read errors --- src/dataprocessor_p.cpp | 46 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/src/dataprocessor_p.cpp b/src/dataprocessor_p.cpp index fcadaac..905f81f 100644 --- a/src/dataprocessor_p.cpp +++ b/src/dataprocessor_p.cpp @@ -368,8 +368,20 @@ Frame Frame::readFrame(QIODevice *pIoDevice) //TODO: Handle return value bytesRead = pIoDevice->read(reinterpret_cast(length), 2); payloadLength = qFromBigEndian(reinterpret_cast(length)); + if (payloadLength < 126) + { + //see http://tools.ietf.org/html/rfc6455#page-28 paragraph 5.2 + //"in all cases, the minimal number of bytes MUST be used to encode + //the length, for example, the length of a 124-byte-long string + //can't be encoded as the sequence 126, 0, 124" + frame.setError(QWebSocketProtocol::CC_PROTOCOL_ERROR, QObject::tr("Lengths smaller than 126 must be expressed as one byte.")); + processingState = PS_DISPATCH_RESULT; + } + else + { processingState = hasMask ? PS_READ_MASK : PS_READ_PAYLOAD; } + } else { WAIT_FOR_MORE_DATA(2); @@ -382,13 +394,32 @@ Frame Frame::readFrame(QIODevice *pIoDevice) if (pIoDevice->bytesAvailable() >= 8) { uchar length[8] = {0}; - //TODO: Handle return value bytesRead = pIoDevice->read(reinterpret_cast(length), 8); + if (bytesRead < 8) + { + frame.setError(QWebSocketProtocol::CC_ABNORMAL_DISCONNECTION, QObject::tr("Something went wrong during reading from the network.")); + processingState = PS_DISPATCH_RESULT; + } + else + { //Most significant bit must be set to 0 as per http://tools.ietf.org/html/rfc6455#section-5.2 - //TODO: Do we check for that? + //TODO: Do we check for that? Now we just strip off the highest bit payloadLength = qFromBigEndian(length) & ~(1ULL << 63); + if (payloadLength < 0xFFFFu) + { + //see http://tools.ietf.org/html/rfc6455#page-28 paragraph 5.2 + //"in all cases, the minimal number of bytes MUST be used to encode + //the length, for example, the length of a 124-byte-long string + //can't be encoded as the sequence 126, 0, 124" + frame.setError(QWebSocketProtocol::CC_PROTOCOL_ERROR, QObject::tr("Lengths smaller than 65536 (2^16) must be expressed as 2 bytes.")); + processingState = PS_DISPATCH_RESULT; + } + else + { processingState = hasMask ? PS_READ_MASK : PS_READ_PAYLOAD; } + } + } else { WAIT_FOR_MORE_DATA(8); @@ -429,15 +460,24 @@ Frame Frame::readFrame(QIODevice *pIoDevice) if (bytesAvailable >= payloadLength) { frame.m_payload = pIoDevice->read(payloadLength); + //payloadLength can be safely cast to an integer, as the MAX_FRAME_SIZE_IN_BYTES = MAX_INT + if (frame.m_payload.length() != static_cast(payloadLength)) //some error occurred; refer to the Qt documentation + { + frame.setError(QWebSocketProtocol::CC_ABNORMAL_DISCONNECTION, QObject::tr("Some serious error occurred while reading from the network.")); + processingState = PS_DISPATCH_RESULT; + } + else + { if (hasMask) { QWebSocketProtocol::mask(&frame.m_payload, frame.m_mask); } processingState = PS_DISPATCH_RESULT; } + } else { - WAIT_FOR_MORE_DATA(payloadLength); + WAIT_FOR_MORE_DATA(payloadLength); //if payload is too big, then this will timeout } } break; -- 2.7.4