Skip to content

Commit 826aaf0

Browse files
committed
Fix frame spillover when not read quickly enough
When Frame.parser is given more data than expected, the next frame's header + contents can end up as part of the payload, causing a UTF-8 validation error, or ends up being thrown away. This can happen in the SSL case if we read slowly and allow the socket's buffer to fill up a little. This commit fixes that by amending WebSocket.once() to only provide bytes <= reading_buffer_size to the stream parser and keeping the rest in a buffer, giving the Frame a chance to stop receiving data at a frame boundary. Fixes: #218
1 parent cdf50bd commit 826aaf0

File tree

1 file changed

+14
-11
lines changed

1 file changed

+14
-11
lines changed

ws4py/websocket.py

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -387,25 +387,28 @@ def once(self):
387387
logger.debug("WebSocket is already terminated")
388388
return False
389389
try:
390-
b = self.sock.recv(self.reading_buffer_size)
391-
if self._is_secure:
392-
b += self._get_from_pending()
393-
if not b:
394-
return False
395-
self.buf += b
390+
if not self.buf:
391+
b = self.sock.recv(self.reading_buffer_size)
392+
if self._is_secure:
393+
b += self._get_from_pending()
394+
if not b:
395+
return False
396+
self.buf += b
396397
except (socket.error, OSError, pyOpenSSLError) as e:
397398
if hasattr(e, "errno") and e.errno == errno.EINTR:
398399
pass
399400
else:
400401
self.unhandled_error(e)
401402
return False
402403
else:
403-
# process as much as we can
404-
# the process will stop either if there is no buffer left
405-
# or if the stream is closed
406-
if not self.process(self.buf):
404+
# handle spillover to prevent overfilling a frame
405+
buf = self.buf[:self.reading_buffer_size]
406+
remaining = self.buf[self.reading_buffer_size:]
407+
408+
if not self.process(buf):
407409
return False
408-
self.buf = b""
410+
411+
self.buf = remaining
409412

410413
return True
411414

0 commit comments

Comments
 (0)