FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

gh-159049: Fix reference cycles after a failed TLS handshake in async… · python/cpython@7dbc797 · GitHub

Repository navigation

Commit 7dbc797

Browse files
authored
gh-159049: Fix reference cycles after a failed TLS handshake in asyncio (#159140)
1 parent 0f2eb5a commit 7dbc797

4 files changed

Lines changed: 68 additions & 0 deletions

File tree

‎Lib/asyncio/base_events.py‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1244,6 +1244,7 @@ async def _create_connection_transport(
12441244
await waiter
12451245
except:
12461246
transport.close()
1247+
waiter = None
12471248
raise
12481249

12491250
return transport, protocol
@@ -1381,6 +1382,7 @@ async def start_tls(self, transport, protocol, sslcontext, *,
13811382
transport.close()
13821383
conmade_cb.cancel()
13831384
resume_cb.cancel()
1385+
waiter = None
13841386
raise
13851387

13861388
return ssl_protocol._app_transport

‎Lib/asyncio/selector_events.py‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1225,6 +1225,7 @@ def _call_connection_lost(self, exc):
12251225
super()._call_connection_lost(exc)
12261226
finally:
12271227
self._write_ready = None
1228+
self._read_ready_cb = None
12281229
if self._empty_waiter is not None:
12291230
self._empty_waiter.set_exception(
12301231
ConnectionError("Connection is closed by peer"))

‎Lib/test/test_asyncio/test_sslproto.py‎

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -832,6 +832,68 @@ async def client(addr):
832832
self.assertIsInstance(server_err, ssl.SSLError)
833833
self.assertIn('ALERT_UNKNOWN_CA', server_err.reason or '')
834834

835+
def test_create_connection_ssl_failed_certificate_no_cycles(self):
836+
# gh-159049
837+
sslctx = test_utils.simple_server_sslcontext()
838+
client_sslctx = test_utils.simple_client_sslcontext(
839+
disable_verify=False)
840+
transports = []
841+
842+
def server(sock):
843+
try:
844+
sock.start_tls(sslctx, server_side=True)
845+
except OSError:
846+
pass
847+
848+
connection_made = sslproto.SSLProtocol.connection_made
849+
850+
def remember_transport(proto, tr):
851+
transports.append(weakref.ref(tr))
852+
connection_made(proto, tr)
853+
854+
async def conn(addr):
855+
try:
856+
await self.loop.create_connection(
857+
asyncio.Protocol, *addr,
858+
ssl=client_sslctx, server_hostname='')
859+
except ssl.SSLCertVerificationError:
860+
pass
861+
862+
support.gc_collect()
863+
with (self.tcp_server(server) as srv, support.disable_gc(),
864+
mock.patch.object(sslproto.SSLProtocol, 'connection_made',
865+
remember_transport)):
866+
self.loop.run_until_complete(conn(srv.addr))
867+
self.assertEqual([tr() for tr in transports], [None])
868+
869+
def test_start_tls_failed_certificate_no_cycles(self):
870+
# gh-159049
871+
sslctx = test_utils.simple_server_sslcontext()
872+
client_sslctx = test_utils.simple_client_sslcontext(
873+
disable_verify=False)
874+
transports = []
875+
876+
def server(sock):
877+
try:
878+
sock.start_tls(sslctx, server_side=True)
879+
except OSError:
880+
pass
881+
882+
async def client(addr):
883+
tr, proto = await self.loop.create_connection(
884+
asyncio.Protocol, *addr)
885+
transports.append(weakref.ref(tr))
886+
try:
887+
await self.loop.start_tls(
888+
tr, proto, client_sslctx, server_hostname='')
889+
except ssl.SSLCertVerificationError:
890+
pass
891+
892+
support.gc_collect()
893+
with self.tcp_server(server) as srv, support.disable_gc():
894+
self.loop.run_until_complete(client(srv.addr))
895+
self.assertEqual([tr() for tr in transports], [None])
896+
835897
def test_create_server_ssl_failed_handshake_sends_alert(self):
836898
# gh-98078: when the handshake fails, the server must send the
837899
# fatal TLS alert generated by OpenSSL to the client before
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix reference cycles in :meth:`asyncio.loop.create_connection` and
2+
:meth:`asyncio.loop.start_tls` after a failed TLS handshake.
3+
Patch by Timofei Ivankov.

0 commit comments

Comments
 (0)

Back | FazBrowse Home | New Git URL