Skip to content

permessage-deflate: message slightly exceeding max_size is truncated instead of rejected #1715

@Kludex

Description

@Kludex

With permessage-deflate, a message whose decompressed size exceeds max_size by 1-2 bytes is silently truncated to max_size instead of being rejected with PayloadTooBig. Larger overages are rejected correctly - the unconsumed_tail check misses the case where all compressed input was consumed while output is still pending in the decompressor.

from websockets.client import ClientProtocol
from websockets.extensions.permessage_deflate import ClientPerMessageDeflateFactory, ServerPerMessageDeflateFactory
from websockets.server import ServerProtocol
from websockets.uri import parse_uri

MAX_SIZE = 2**24

client = ClientProtocol(parse_uri("ws://localhost/"), extensions=[ClientPerMessageDeflateFactory()])
server = ServerProtocol(extensions=[ServerPerMessageDeflateFactory()], max_size=MAX_SIZE)

client.send_request(client.connect())
server.receive_data(b"".join(client.data_to_send()))
server.send_response(server.accept(server.events_received()[0]))
client.receive_data(b"".join(server.data_to_send()))
client.events_received()

client.send_binary(b"\x01" * (MAX_SIZE + 1))  # one byte over max_size
server.receive_data(b"".join(client.data_to_send()))

print(server.parser_exc)  # None - expected PayloadTooBig
print(len(server.events_received()[0].data))  # 16777216 - silently truncated

Reproduced on 16.0. Found while moving Uvicorn off the legacy implementation: Kludex/uvicorn#2985.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions