Skip to content

Commit b9abe98

Browse files
obiltschnigmatejk
authored andcommitted
Merge pull request #4838 from d3matt/odd_nonblocking_receive_incorrect_mask
fix(Net) bad mask with odd number of bytes
1 parent af36c9b commit b9abe98

File tree

2 files changed

+12
-7
lines changed

2 files changed

+12
-7
lines changed

Net/include/Poco/Net/WebSocketImpl.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ class Net_API WebSocketImpl: public StreamSocketImpl
121121
int payloadLength = 0;
122122
int remainingPayloadLength = 0;
123123
Poco::Buffer<char> payload{0};
124+
int maskOffset = 0;
124125
};
125126

126127
struct SendState
@@ -133,7 +134,7 @@ class Net_API WebSocketImpl: public StreamSocketImpl
133134

134135
int peekHeader(ReceiveState& receiveState);
135136
void skipHeader(int headerLength);
136-
int receivePayload(char *buffer, int payloadLength, char mask[MASK_LENGTH], bool useMask);
137+
int receivePayload(char *buffer, int payloadLength, char mask[MASK_LENGTH], bool useMask, int maskOffset);
137138
int receiveNBytes(void* buffer, int length);
138139
int receiveSomeBytes(char* buffer, int length);
139140
int peekSomeBytes(char* buffer, int length);

Net/src/WebSocketImpl.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -262,14 +262,14 @@ void WebSocketImpl::setMaxPayloadSize(int maxPayloadSize)
262262
}
263263

264264

265-
int WebSocketImpl::receivePayload(char *buffer, int payloadLength, char mask[MASK_LENGTH], bool useMask)
265+
int WebSocketImpl::receivePayload(char *buffer, int payloadLength, char mask[MASK_LENGTH], bool useMask, int maskOffset)
266266
{
267267
int received = receiveNBytes(reinterpret_cast<char*>(buffer), payloadLength);
268268
if (received > 0 && useMask)
269269
{
270270
for (int i = 0; i < received; i++)
271271
{
272-
buffer[i] ^= mask[i % MASK_LENGTH];
272+
buffer[i] ^= mask[(i + maskOffset) % MASK_LENGTH];
273273
}
274274
}
275275
return received;
@@ -297,7 +297,7 @@ int WebSocketImpl::receiveBytes(void* buffer, int length, int)
297297

298298
skipHeader(_receiveState.headerLength);
299299

300-
if (receivePayload(reinterpret_cast<char*>(buffer), payloadLength, _receiveState.mask, _receiveState.useMask) != payloadLength)
300+
if (receivePayload(reinterpret_cast<char*>(buffer), payloadLength, _receiveState.mask, _receiveState.useMask, 0) != payloadLength)
301301
throw WebSocketException("Incomplete frame received", WebSocket::WS_ERR_INCOMPLETE_FRAME);
302302

303303
return payloadLength;
@@ -326,17 +326,19 @@ int WebSocketImpl::receiveBytes(void* buffer, int length, int)
326326
throw WebSocketException(Poco::format("Insufficient buffer for payload size %d", _receiveState.payloadLength), WebSocket::WS_ERR_PAYLOAD_TOO_BIG);
327327
}
328328
int payloadOffset = _receiveState.payloadLength - _receiveState.remainingPayloadLength;
329-
int n = receivePayload(_receiveState.payload.begin() + payloadOffset, _receiveState.remainingPayloadLength, _receiveState.mask, _receiveState.useMask);
329+
int n = receivePayload(_receiveState.payload.begin() + payloadOffset, _receiveState.remainingPayloadLength, _receiveState.mask, _receiveState.useMask, _receiveState.maskOffset);
330330
if (n > 0)
331331
{
332332
_receiveState.remainingPayloadLength -= n;
333333
if (_receiveState.remainingPayloadLength == 0)
334334
{
335+
_receiveState.maskOffset = 0;
335336
std::memcpy(buffer, _receiveState.payload.begin(), _receiveState.payloadLength);
336337
return _receiveState.payloadLength;
337338
}
338339
else
339340
{
341+
_receiveState.maskOffset += n;
340342
return -1;
341343
}
342344
}
@@ -369,7 +371,7 @@ int WebSocketImpl::receiveBytes(Poco::Buffer<char>& buffer, int, const Poco::Tim
369371
std::size_t oldSize = buffer.size();
370372
buffer.resize(oldSize + payloadLength);
371373

372-
if (receivePayload(buffer.begin() + oldSize, payloadLength, _receiveState.mask, _receiveState.useMask) != payloadLength)
374+
if (receivePayload(buffer.begin() + oldSize, payloadLength, _receiveState.mask, _receiveState.useMask, 0) != payloadLength)
373375
throw WebSocketException("Incomplete frame received", WebSocket::WS_ERR_INCOMPLETE_FRAME);
374376

375377
return payloadLength;
@@ -387,12 +389,13 @@ int WebSocketImpl::receiveBytes(Poco::Buffer<char>& buffer, int, const Poco::Tim
387389
_receiveState.payload.resize(payloadLength, false);
388390
}
389391
int payloadOffset = _receiveState.payloadLength - _receiveState.remainingPayloadLength;
390-
int n = receivePayload(_receiveState.payload.begin() + payloadOffset, _receiveState.remainingPayloadLength, _receiveState.mask, _receiveState.useMask);
392+
int n = receivePayload(_receiveState.payload.begin() + payloadOffset, _receiveState.remainingPayloadLength, _receiveState.mask, _receiveState.useMask, _receiveState.maskOffset);
391393
if (n > 0)
392394
{
393395
_receiveState.remainingPayloadLength -= n;
394396
if (_receiveState.remainingPayloadLength == 0)
395397
{
398+
_receiveState.maskOffset = 0;
396399
std::size_t oldSize = buffer.size();
397400
buffer.resize(oldSize + _receiveState.payloadLength);
398401

@@ -401,6 +404,7 @@ int WebSocketImpl::receiveBytes(Poco::Buffer<char>& buffer, int, const Poco::Tim
401404
}
402405
else
403406
{
407+
_receiveState.maskOffset += n;
404408
return -1;
405409
}
406410
}

0 commit comments

Comments
 (0)