Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

websocket: fix bug where interleaved control frame breaks compression #3353

Open
wants to merge 1 commit into
base: branch6.4
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 7 additions & 2 deletions tornado/websocket.py
Original file line number Diff line number Diff line change
Expand Up @@ -1117,7 +1117,9 @@ async def _receive_frame(self) -> None:
reserved_bits = header & self.RSV_MASK
opcode = header & self.OPCODE_MASK
opcode_is_control = opcode & 0x8
if self._decompressor is not None and opcode != 0:
# Control frames are never compressed, but can also be interleaved with a series
# of fragmented data frames. Don't let them affect _frame_compressed
if self._decompressor is not None and opcode != 0 and not opcode_is_control:
# Compression flag is present in the first frame's header,
# but we can't decompress until we have all the frames of
# the message.
Expand Down Expand Up @@ -1197,7 +1199,10 @@ def _handle_message(self, opcode: int, data: bytes) -> "Optional[Future[None]]":
if self.client_terminated:
return None

if self._frame_compressed:
opcode_is_control = opcode & 0x8
# _frame_compressed does not apply to control frames.
# Control frames are never compressed.
if self._frame_compressed and not opcode_is_control:
assert self._decompressor is not None
try:
data = self._decompressor.decompress(data)
Expand Down