mirror of
https://github.com/pocoproject/poco.git
synced 2025-02-13 03:10:14 +01:00
fix(Net) bad mask with odd number of bytes
Receiving an odd number of bytes in non-blocking mode results in using the wrong bytes to unmask the payload. Keep track of the number of payload bytes that have been unmasked.
This commit is contained in:
parent
4ca735d7d8
commit
0cc3ab4d13
@ -121,6 +121,7 @@ protected:
|
|||||||
int payloadLength = 0;
|
int payloadLength = 0;
|
||||||
int remainingPayloadLength = 0;
|
int remainingPayloadLength = 0;
|
||||||
Poco::Buffer<char> payload{0};
|
Poco::Buffer<char> payload{0};
|
||||||
|
int maskOffset = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SendState
|
struct SendState
|
||||||
@ -133,7 +134,7 @@ protected:
|
|||||||
|
|
||||||
int peekHeader(ReceiveState& receiveState);
|
int peekHeader(ReceiveState& receiveState);
|
||||||
void skipHeader(int headerLength);
|
void skipHeader(int headerLength);
|
||||||
int receivePayload(char *buffer, int payloadLength, char mask[MASK_LENGTH], bool useMask);
|
int receivePayload(char *buffer, int payloadLength, char mask[MASK_LENGTH], bool useMask, int maskOffset);
|
||||||
int receiveNBytes(void* buffer, int length);
|
int receiveNBytes(void* buffer, int length);
|
||||||
int receiveSomeBytes(char* buffer, int length);
|
int receiveSomeBytes(char* buffer, int length);
|
||||||
int peekSomeBytes(char* buffer, int length);
|
int peekSomeBytes(char* buffer, int length);
|
||||||
|
@ -262,14 +262,14 @@ void WebSocketImpl::setMaxPayloadSize(int maxPayloadSize)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int WebSocketImpl::receivePayload(char *buffer, int payloadLength, char mask[MASK_LENGTH], bool useMask)
|
int WebSocketImpl::receivePayload(char *buffer, int payloadLength, char mask[MASK_LENGTH], bool useMask, int maskOffset)
|
||||||
{
|
{
|
||||||
int received = receiveNBytes(reinterpret_cast<char*>(buffer), payloadLength);
|
int received = receiveNBytes(reinterpret_cast<char*>(buffer), payloadLength);
|
||||||
if (received > 0 && useMask)
|
if (received > 0 && useMask)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < received; i++)
|
for (int i = 0; i < received; i++)
|
||||||
{
|
{
|
||||||
buffer[i] ^= mask[i % MASK_LENGTH];
|
buffer[i] ^= mask[(i + maskOffset) % MASK_LENGTH];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return received;
|
return received;
|
||||||
@ -297,7 +297,7 @@ int WebSocketImpl::receiveBytes(void* buffer, int length, int)
|
|||||||
|
|
||||||
skipHeader(_receiveState.headerLength);
|
skipHeader(_receiveState.headerLength);
|
||||||
|
|
||||||
if (receivePayload(reinterpret_cast<char*>(buffer), payloadLength, _receiveState.mask, _receiveState.useMask) != payloadLength)
|
if (receivePayload(reinterpret_cast<char*>(buffer), payloadLength, _receiveState.mask, _receiveState.useMask, 0) != payloadLength)
|
||||||
throw WebSocketException("Incomplete frame received", WebSocket::WS_ERR_INCOMPLETE_FRAME);
|
throw WebSocketException("Incomplete frame received", WebSocket::WS_ERR_INCOMPLETE_FRAME);
|
||||||
|
|
||||||
return payloadLength;
|
return payloadLength;
|
||||||
@ -326,17 +326,19 @@ int WebSocketImpl::receiveBytes(void* buffer, int length, int)
|
|||||||
throw WebSocketException(Poco::format("Insufficient buffer for payload size %d", _receiveState.payloadLength), WebSocket::WS_ERR_PAYLOAD_TOO_BIG);
|
throw WebSocketException(Poco::format("Insufficient buffer for payload size %d", _receiveState.payloadLength), WebSocket::WS_ERR_PAYLOAD_TOO_BIG);
|
||||||
}
|
}
|
||||||
int payloadOffset = _receiveState.payloadLength - _receiveState.remainingPayloadLength;
|
int payloadOffset = _receiveState.payloadLength - _receiveState.remainingPayloadLength;
|
||||||
int n = receivePayload(_receiveState.payload.begin() + payloadOffset, _receiveState.remainingPayloadLength, _receiveState.mask, _receiveState.useMask);
|
int n = receivePayload(_receiveState.payload.begin() + payloadOffset, _receiveState.remainingPayloadLength, _receiveState.mask, _receiveState.useMask, _receiveState.maskOffset);
|
||||||
if (n > 0)
|
if (n > 0)
|
||||||
{
|
{
|
||||||
_receiveState.remainingPayloadLength -= n;
|
_receiveState.remainingPayloadLength -= n;
|
||||||
if (_receiveState.remainingPayloadLength == 0)
|
if (_receiveState.remainingPayloadLength == 0)
|
||||||
{
|
{
|
||||||
|
_receiveState.maskOffset = 0;
|
||||||
std::memcpy(buffer, _receiveState.payload.begin(), _receiveState.payloadLength);
|
std::memcpy(buffer, _receiveState.payload.begin(), _receiveState.payloadLength);
|
||||||
return _receiveState.payloadLength;
|
return _receiveState.payloadLength;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
_receiveState.maskOffset += n;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -369,7 +371,7 @@ int WebSocketImpl::receiveBytes(Poco::Buffer<char>& buffer, int, const Poco::Tim
|
|||||||
std::size_t oldSize = buffer.size();
|
std::size_t oldSize = buffer.size();
|
||||||
buffer.resize(oldSize + payloadLength);
|
buffer.resize(oldSize + payloadLength);
|
||||||
|
|
||||||
if (receivePayload(buffer.begin() + oldSize, payloadLength, _receiveState.mask, _receiveState.useMask) != payloadLength)
|
if (receivePayload(buffer.begin() + oldSize, payloadLength, _receiveState.mask, _receiveState.useMask, 0) != payloadLength)
|
||||||
throw WebSocketException("Incomplete frame received", WebSocket::WS_ERR_INCOMPLETE_FRAME);
|
throw WebSocketException("Incomplete frame received", WebSocket::WS_ERR_INCOMPLETE_FRAME);
|
||||||
|
|
||||||
return payloadLength;
|
return payloadLength;
|
||||||
@ -387,12 +389,13 @@ int WebSocketImpl::receiveBytes(Poco::Buffer<char>& buffer, int, const Poco::Tim
|
|||||||
_receiveState.payload.resize(payloadLength, false);
|
_receiveState.payload.resize(payloadLength, false);
|
||||||
}
|
}
|
||||||
int payloadOffset = _receiveState.payloadLength - _receiveState.remainingPayloadLength;
|
int payloadOffset = _receiveState.payloadLength - _receiveState.remainingPayloadLength;
|
||||||
int n = receivePayload(_receiveState.payload.begin() + payloadOffset, _receiveState.remainingPayloadLength, _receiveState.mask, _receiveState.useMask);
|
int n = receivePayload(_receiveState.payload.begin() + payloadOffset, _receiveState.remainingPayloadLength, _receiveState.mask, _receiveState.useMask, _receiveState.maskOffset);
|
||||||
if (n > 0)
|
if (n > 0)
|
||||||
{
|
{
|
||||||
_receiveState.remainingPayloadLength -= n;
|
_receiveState.remainingPayloadLength -= n;
|
||||||
if (_receiveState.remainingPayloadLength == 0)
|
if (_receiveState.remainingPayloadLength == 0)
|
||||||
{
|
{
|
||||||
|
_receiveState.maskOffset = 0;
|
||||||
std::size_t oldSize = buffer.size();
|
std::size_t oldSize = buffer.size();
|
||||||
buffer.resize(oldSize + _receiveState.payloadLength);
|
buffer.resize(oldSize + _receiveState.payloadLength);
|
||||||
|
|
||||||
@ -401,6 +404,7 @@ int WebSocketImpl::receiveBytes(Poco::Buffer<char>& buffer, int, const Poco::Tim
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
_receiveState.maskOffset += n;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user