Skip to content

Commit b41b226

Browse files
authored
Merge branch 'main' into fix-imap-buffersize-close
2 parents 956e103 + 036d309 commit b41b226

17 files changed

Lines changed: 317 additions & 84 deletions

‎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/asyncio/windows_events.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -515,11 +515,11 @@ def recvfrom(self, conn, nbytes, flags=0):
515515
return self._register(ov, conn, partial(self._finish_recvfrom,
516516
empty_result=b''))
517517

518-
def recvfrom_into(self, conn, buf, flags=0):
518+
def recvfrom_into(self, conn, buf, nbytes=0):
519519
self._register_with_iocp(conn)
520520
ov = _overlapped.Overlapped(NULL)
521521
try:
522-
ov.WSARecvFromInto(conn.fileno(), buf, flags)
522+
ov.WSARecvFromInto(conn.fileno(), buf, nbytes)
523523
except BrokenPipeError:
524524
return self._result((0, None))
525525

‎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

‎Lib/test/test_asyncio/test_tasks.py‎

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""Tests for tasks.py."""
22

3+
import _thread
34
import collections
45
import contextlib
56
import contextvars
@@ -20,6 +21,7 @@
2021
from asyncio import tasks
2122
from test.test_asyncio import utils as test_utils
2223
from test import support
24+
from test.support import threading_helper
2325
from test.support.script_helper import assert_python_ok
2426

2527

@@ -3095,6 +3097,39 @@ class CTask_CFuture_Tests(BaseTaskTests, SetMethodsTest,
30953097
all_tasks = getattr(tasks, '_c_all_tasks', None)
30963098
current_task = staticmethod(getattr(tasks, '_c_current_task', None))
30973099

3100+
@threading_helper.requires_working_threading()
3101+
def test_task_created_during_thread_state_clear(self):
3102+
loop = self.loop
3103+
task = None
3104+
var = contextvars.ContextVar('var')
3105+
# Avoid recreating the thread state's context after it is cleared.
3106+
task_context = contextvars.Context()
3107+
3108+
async def noop():
3109+
pass
3110+
3111+
class CreatesTaskOnClear:
3112+
def __del__(self):
3113+
nonlocal task
3114+
task = loop.create_task(noop(), context=task_context)
3115+
3116+
def create_finalizer():
3117+
# gh-159041: Run the finalizer when PyThreadState_Clear()
3118+
# clears the thread's context.
3119+
var.set(CreatesTaskOnClear())
3120+
3121+
# threading.Thread owns its Context, so use _thread to make the
3122+
# Context lifetime match the thread state's lifetime.
3123+
handle = _thread.start_joinable_thread(create_finalizer)
3124+
handle.join(support.SHORT_TIMEOUT)
3125+
self.assertTrue(handle.is_done(), 'thread failed to exit')
3126+
self.assertIsNotNone(task)
3127+
3128+
try:
3129+
self.assertEqual(self.all_tasks(loop), {task})
3130+
finally:
3131+
loop.run_until_complete(task)
3132+
30983133
def test_del__log_destroy_pending_segfault(self):
30993134
async def coro():
31003135
pass

‎Lib/test/test_compile.py‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1583,6 +1583,28 @@ def f():
15831583

15841584
self.check_line_numbers(f.__code__, 'JUMP_BACKWARD')
15851585

1586+
def test_backward_jump_conditional_in_loop_in_try(self):
1587+
# gh-130279: The jumps in a loop body, including the backward jump
1588+
# for the untaken branch of a conditional at the end of the body,
1589+
# must be covered by the exception handler of the enclosing try.
1590+
def f(items):
1591+
try:
1592+
for x in items:
1593+
if x < 0:
1594+
raise ValueError(x)
1595+
except KeyboardInterrupt:
1596+
return 'handled'
1597+
1598+
bytecode = dis.Bytecode(f)
1599+
jumps = [instr for instr in bytecode
1600+
if instr.opcode in dis.hasjump]
1601+
self.assertTrue(jumps)
1602+
for instr in jumps:
1603+
with self.subTest(instr=instr):
1604+
self.assertTrue(
1605+
any(entry.start <= instr.offset < entry.end
1606+
for entry in bytecode.exception_entries))
1607+
15861608
def test_big_dict_literal(self):
15871609
# The compiler has a flushing point in "compiler_dict" that calls compiles
15881610
# a portion of the dictionary literal when the loop that iterates over the items

‎Lib/test/test_dis.py‎

Lines changed: 56 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -454,53 +454,52 @@ def foo(a: int, b: str) -> str:
454454
"""
455455

456456
dis_traceback = """\
457-
%4d RESUME 0
457+
%4d RESUME 0
458458
459-
%4d NOP
459+
%4d NOP
460460
461-
%4d L1: LOAD_SMALL_INT 1
462-
LOAD_SMALL_INT 0
463-
--> BINARY_OP 11 (/)
464-
POP_TOP
461+
%4d L1: LOAD_SMALL_INT 1
462+
LOAD_SMALL_INT 0
463+
--> BINARY_OP 11 (/)
464+
POP_TOP
465465
466-
%4d L2: LOAD_FAST_CHECK 1 (tb)
467-
RETURN_VALUE
466+
%4d L2: LOAD_FAST_CHECK 1 (tb)
467+
RETURN_VALUE
468468
469-
-- L3: PUSH_EXC_INFO
469+
-- L3: PUSH_EXC_INFO
470470
471-
%4d LOAD_GLOBAL 0 (Exception)
472-
CHECK_EXC_MATCH
473-
POP_JUMP_IF_FALSE 24 (to L9)
474-
L4: NOT_TAKEN
475-
L5: STORE_FAST 0 (e)
471+
%4d LOAD_GLOBAL 0 (Exception)
472+
CHECK_EXC_MATCH
473+
POP_JUMP_IF_FALSE 24 (to L7)
474+
NOT_TAKEN
475+
STORE_FAST 0 (e)
476476
477-
%4d L6: LOAD_FAST 0 (e)
478-
LOAD_ATTR 2 (__traceback__)
479-
STORE_FAST 1 (tb)
480-
L7: POP_EXCEPT
481-
LOAD_COMMON_CONSTANT 7 (None)
482-
STORE_FAST 0 (e)
483-
DELETE_FAST 0 (e)
477+
%4d L4: LOAD_FAST 0 (e)
478+
LOAD_ATTR 2 (__traceback__)
479+
STORE_FAST 1 (tb)
480+
L5: POP_EXCEPT
481+
LOAD_COMMON_CONSTANT 7 (None)
482+
STORE_FAST 0 (e)
483+
DELETE_FAST 0 (e)
484484
485-
%4d LOAD_FAST 1 (tb)
486-
RETURN_VALUE
485+
%4d LOAD_FAST 1 (tb)
486+
RETURN_VALUE
487487
488-
-- L8: LOAD_COMMON_CONSTANT 7 (None)
489-
STORE_FAST 0 (e)
490-
DELETE_FAST 0 (e)
491-
RERAISE 1
488+
-- L6: LOAD_COMMON_CONSTANT 7 (None)
489+
STORE_FAST 0 (e)
490+
DELETE_FAST 0 (e)
491+
RERAISE 1
492492
493-
%4d L9: RERAISE 0
493+
%4d L7: RERAISE 0
494494
495-
-- L10: COPY 3
496-
POP_EXCEPT
497-
RERAISE 1
495+
-- L8: COPY 3
496+
POP_EXCEPT
497+
RERAISE 1
498498
ExceptionTable:
499499
L1 to L2 -> L3 [0]
500-
L3 to L4 -> L10 [1] lasti
501-
L5 to L6 -> L10 [1] lasti
502-
L6 to L7 -> L8 [1] lasti
503-
L8 to L10 -> L10 [1] lasti
500+
L3 to L4 -> L8 [1] lasti
501+
L4 to L5 -> L6 [1] lasti
502+
L6 to L8 -> L8 [1] lasti
504503
""" % (TRACEBACK_CODE.co_firstlineno,
505504
TRACEBACK_CODE.co_firstlineno + 1,
506505
TRACEBACK_CODE.co_firstlineno + 2,
@@ -569,11 +568,11 @@ def _with(c):
569568
%4d L3: PUSH_EXC_INFO
570569
WITH_EXCEPT_START
571570
TO_BOOL
572-
POP_JUMP_IF_TRUE 2 (to L6)
573-
L4: NOT_TAKEN
574-
L5: RERAISE 2
575-
L6: POP_TOP
576-
L7: POP_EXCEPT
571+
POP_JUMP_IF_TRUE 2 (to L4)
572+
NOT_TAKEN
573+
RERAISE 2
574+
L4: POP_TOP
575+
L5: POP_EXCEPT
577576
POP_TOP
578577
POP_TOP
579578
POP_TOP
@@ -583,13 +582,12 @@ def _with(c):
583582
LOAD_COMMON_CONSTANT 7 (None)
584583
RETURN_VALUE
585584
586-
-- L8: COPY 3
585+
-- L6: COPY 3
587586
POP_EXCEPT
588587
RERAISE 1
589588
ExceptionTable:
590589
L1 to L2 -> L3 [2] lasti
591-
L3 to L4 -> L8 [4] lasti
592-
L5 to L7 -> L8 [4] lasti
590+
L3 to L5 -> L6 [4] lasti
593591
""" % (_with.__code__.co_firstlineno,
594592
_with.__code__.co_firstlineno + 1,
595593
_with.__code__.co_firstlineno + 2,
@@ -664,11 +662,11 @@ async def _asyncwith(c):
664662
L20: CLEANUP_THROW
665663
L21: END_SEND
666664
TO_BOOL
667-
POP_JUMP_IF_TRUE 2 (to L24)
668-
L22: NOT_TAKEN
669-
L23: RERAISE 2
670-
L24: POP_TOP
671-
L25: POP_EXCEPT
665+
POP_JUMP_IF_TRUE 2 (to L22)
666+
NOT_TAKEN
667+
RERAISE 2
668+
L22: POP_TOP
669+
L23: POP_EXCEPT
672670
POP_TOP
673671
POP_TOP
674672
POP_TOP
@@ -678,25 +676,24 @@ async def _asyncwith(c):
678676
LOAD_COMMON_CONSTANT 7 (None)
679677
RETURN_VALUE
680678
681-
-- L26: COPY 3
679+
-- L24: COPY 3
682680
POP_EXCEPT
683681
RERAISE 1
684-
L27: CALL_INTRINSIC_1 3 (INTRINSIC_STOPITERATION_ERROR)
682+
L25: CALL_INTRINSIC_1 3 (INTRINSIC_STOPITERATION_ERROR)
685683
RERAISE 1
686684
ExceptionTable:
687-
L1 to L3 -> L27 [0] lasti
685+
L1 to L3 -> L25 [0] lasti
688686
L3 to L4 -> L12 [5]
689-
L4 to L6 -> L27 [0] lasti
687+
L4 to L6 -> L25 [0] lasti
690688
L6 to L7 -> L16 [2] lasti
691-
L7 to L9 -> L27 [0] lasti
689+
L7 to L9 -> L25 [0] lasti
692690
L9 to L10 -> L14 [3]
693-
L10 to L13 -> L27 [0] lasti
694-
L14 to L15 -> L27 [0] lasti
695-
L16 to L18 -> L26 [4] lasti
691+
L10 to L13 -> L25 [0] lasti
692+
L14 to L15 -> L25 [0] lasti
693+
L16 to L18 -> L24 [4] lasti
696694
L18 to L19 -> L20 [8]
697-
L19 to L22 -> L26 [4] lasti
698-
L23 to L25 -> L26 [4] lasti
699-
L25 to L27 -> L27 [0] lasti
695+
L19 to L23 -> L24 [4] lasti
696+
L23 to L25 -> L25 [0] lasti
700697
""" % (_asyncwith.__code__.co_firstlineno,
701698
_asyncwith.__code__.co_firstlineno + 1,
702699
_asyncwith.__code__.co_firstlineno + 2,

0 commit comments

Comments
 (0)