Skip to content

Commit c1946f0

Browse files
committed
gh-152431: Update StreamReader transport after asyncio TLS upgrade
StreamReaderProtocol._replace_transport only updated its own transport reference. After start_tls, the linked StreamReader still held the old transport, causing reads to use the wrong connection.
1 parent ba0c0e6 commit c1946f0

3 files changed

Lines changed: 35 additions & 0 deletions

File tree

Lib/asyncio/streams.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,9 @@ def _stream_reader(self):
216216
def _replace_transport(self, transport):
217217
self._transport = transport
218218
self._over_ssl = transport.get_extra_info('sslcontext') is not None
219+
reader = self._stream_reader
220+
if reader is not None:
221+
reader._transport = transport
219222

220223
def connection_made(self, transport):
221224
if self._reject_connection:

Lib/test/test_asyncio/test_ssl.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1737,6 +1737,36 @@ async def client(addr):
17371737
loop.run_until_complete(client(srv.addr))
17381738

17391739

1740+
async def test_start_tls_updates_stream_reader_transport(self):
1741+
# gh-152431: after start_tls, the StreamReader must use the new
1742+
# transport, not the old one.
1743+
srv_ctx = test_utils.simple_server_sslcontext()
1744+
cli_ctx = test_utils.simple_client_sslcontext()
1745+
1746+
async def handler(reader, writer):
1747+
writer.close()
1748+
1749+
srv = await asyncio.start_server(handler, '127.0.0.1', 0)
1750+
addr = srv.sockets[0].getsockname()
1751+
1752+
reader, writer = await asyncio.open_connection(*addr)
1753+
1754+
old_transport = reader._transport
1755+
self.assertIsNotNone(old_transport)
1756+
1757+
new_transport = await self.loop.start_tls(
1758+
writer.transport, writer._protocol, srv_ctx,
1759+
server_side=False, ssl_handshake_timeout=self.TIMEOUT)
1760+
1761+
# The reader should now reference the TLS transport
1762+
self.assertIs(reader._transport, new_transport)
1763+
self.assertIsNot(reader._transport, old_transport)
1764+
1765+
writer.close()
1766+
srv.close()
1767+
await srv.wait_closed()
1768+
1769+
17401770
###############################################################################
17411771
# Socket Testing Utilities
17421772
###############################################################################
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix :meth:`asyncio.StreamWriter.start_tls` to update the linked
2+
:class:`~asyncio.StreamReader` transport after the TLS handshake.

0 commit comments

Comments
 (0)