Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGES/13536.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fixed the WebSocket reader accepting close code ``1006`` in a Close frame
received from the peer -- by :user:`arshsmith1`.
7 changes: 6 additions & 1 deletion aiohttp/_websocket/reader_py.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import sys
Comment thread
Dreamsorcerer marked this conversation as resolved.
import weakref
from collections import deque
from typing import Final
Comment thread
Dreamsorcerer marked this conversation as resolved.
Outdated

from ..base_protocol import BaseProtocol
from ..compression_utils import TooManyMembersError, ZLibDecompressor
Expand All @@ -26,7 +27,11 @@
WSMsgType,
)

ALLOWED_CLOSE_CODES: set[int] = {int(i) for i in WSCloseCode}
# ABNORMAL_CLOSURE is used internally, should never be accepted from a client.
# https://datatracker.ietf.org/doc/html/rfc6455#section-7.4.1
ALLOWED_CLOSE_CODES: Final = {int(i) for i in WSCloseCode} - {
Comment thread
Dreamsorcerer marked this conversation as resolved.
Outdated
int(WSCloseCode.ABNORMAL_CLOSURE)
}

# States for the reader, used to parse the WebSocket frame
# integer values are used so they can be cythonized
Expand Down
14 changes: 14 additions & 0 deletions tests/test_websocket_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,20 @@ def test_close_frame_invalid_code_above_range(
assert ctx.value.code == WSCloseCode.PROTOCOL_ERROR


@pytest.mark.parametrize("code", (1004, 1005, 1006, 1015))
def test_close_frame_reserved_code(parser: PatchableWebSocketReader, code: int) -> None:
# https://datatracker.ietf.org/doc/html/rfc6455#section-7.4.1
# 1004, 1005, 1006 and 1015 are resreved and forbidden as a
# status code in a Close frame on the wire. 1006 is a WSCloseCode member
# (aiohttp uses it locally), so it must still be rejected on receipt.
data = build_close_frame(code=code)

with pytest.raises(WebSocketError) as ctx:
parser._feed_data(data)

assert ctx.value.code == WSCloseCode.PROTOCOL_ERROR


def test_close_frame_unicode_err(parser: PatchableWebSocketReader) -> None:
data = build_close_frame(code=1000, message=b"\xf4\x90\x80\x80")

Expand Down
Loading