GeezerVisonThe World Wide Web, restored to 800 pixels of glory. |
| Home|About|Gaming cabinet|Archives|How it works|Starter sites |
GeezerVison is showing github.com — Regression in ssl module between 3.13.5 and 3.13.6: reading from a TLS-encrypted connection blocks · Issue #137583 · python/cpython Closed Labels 3.13only security fixesonly security fixes3.15bugs and security fixesbugs and security fixesdeferred-blockerextension-modulesC modules in the Modules dirC modules in the Modules dirtopic-SSLtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error DescriptionBug reportBug description:The script below works with 3.13.5 and fails with 3.13.6. It's a straightforward socket server and client with TLS enabled. Under 3.13.5, it runs successfully. Under 3.13.6, when the server calls This is a minimal reproduction version of python-websockets/websockets#1648. I performed the reproduction on macOS while the person reporting the bug was on Linux so I think it's platform-independent. To trigger the bug, the client must read from the connection in a separate thread. If you remove that thread, the bug doesn't happen. (For context, I do this because websockets is architecture with a Sans-I/O layer so I need a background thread to pump bytes received from the network into the Sans-I/O parser.) Before you run the script, you must download https://github.com/python-websockets/websockets/blob/main/tests/test_localhost.pem and store it next to the file where you saved the Python script. import os import socket import ssl import threading TLS_HANDSHAKE_TIMEOUT = 1 print("If Python locks hard:") print("kill -TERM", os.getpid()) print() # Create TLS contexts with a self-signed certificate. Download it here: # https://github.com/python-websockets/websockets/blob/main/tests/test_localhost.pem server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) server_context.load_cert_chain(b"test_localhost.pem") # Work around https://github.com/openssl/openssl/issues/7967 server_context.num_tickets = 0 client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) client_context.load_verify_locations(b"test_localhost.pem") # Start a socket server. Nothing fancy here. In a realistic server, we would # have `serve_forever` with a `while True:` loop. For a minimal reproduction, # `serve_one` is enough, as the bug occurs on the first request. server_sock = socket.create_server(("localhost", 0)) server_port = server_sock.getsockname()[1] server_sock = server_context.wrap_socket( server_sock, server_side=True, # Delay TLS handshake until after we set a timeout on the socket. do_handshake_on_connect=False, ) def conn_handler(sock, addr) -> None: print("server accepted connection from", addr) sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, True) sock.settimeout(TLS_HANDSHAKE_TIMEOUT) assert isinstance(sock, ssl.SSLSocket) sock.do_handshake() sock.settimeout(None) handshake = sock.recv(4096) print("server rcvd:") print(handshake.decode()) print() def serve_one(): sock, addr = server_sock.accept() handler_thread = threading.Thread(target=conn_handler, args=(sock, addr)) handler_thread.start() print("server listening on port", server_port) server_thread = threading.Thread(target=serve_one) server_thread.start() # Connect a client to the server. Again, nothing fancy. client_sock = socket.create_connection(("localhost", server_port)) client_sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, True) client_sock.settimeout(TLS_HANDSHAKE_TIMEOUT) client_sock = client_context.wrap_socket( client_sock, server_hostname="localhost", ) client_sock.settimeout(None) ### The bug happens only when we're reading from the client socket too! ### def recv_one_event(): msg = client_sock.recv(4096) print("client rcvd:") print(msg.decode()) print() client_background_thread = threading.Thread(target=recv_one_event) client_background_thread.start() ### If you remove client_background_thread.start(), it doesn't happen. ### handshake = ( b"GET / HTTP/1.1\r\n" b"Host: 127.0.0.1:51970\r\n" b"Upgrade: websocket\r\n" b"Connection: Upgrade\r\n" b"Sec-WebSocket-Key: jjSVQ7XPjx2GIXKfQ49QDQ==\r\n" b"Sec-WebSocket-Version: 13\r\n" b"Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits\r\n" b"User-Agent: Python/3.13 websockets/15.0.1\r\n" b"\r\n" ) print("client send:") print(handshake.decode()) print() client_sock.sendall(handshake) CPython versions tested on:3.13 Operating systems tested on:macOS Linked PRsReacted by Gregory P. Smith, Holger Bruch and Zelo-on Activity
MetadataMetadataLabels3.13only security fixesonly security fixes3.15bugs and security fixesbugs and security fixesdeferred-blockerextension-modulesC modules in the Modules dirC modules in the Modules dirtopic-SSLtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error Projects
MilestoneRelationshipsDevelopmentIssue actions |
| You are visitor 01402520 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required. |