Skip to content

Commit 37f8e99

Browse files
disallow multiple initializations of asyncio tasks and futures
1 parent 2a820e2 commit 37f8e99

File tree

3 files changed

+6
-76
lines changed

3 files changed

+6
-76
lines changed

Lib/test/test_asyncio/test_futures.py

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1091,33 +1091,6 @@ def __getattribute__(self, name):
10911091
fut.add_done_callback(fut_callback_0)
10921092
self.assertRaises(ReachableCode, fut.set_result, "boom")
10931093

1094-
def test_use_after_free_on_fut_context_0_with_evil__getattribute__(self):
1095-
# see: https://github.com/python/cpython/issues/125984
1096-
1097-
class EvilEventLoop(SimpleEvilEventLoop):
1098-
def call_soon(self, *args, **kwargs):
1099-
super().call_soon(*args, **kwargs)
1100-
raise ReachableCode
1101-
1102-
def __getattribute__(self, name):
1103-
if name == 'call_soon':
1104-
# resets the future's event loop
1105-
fut.__init__(loop=SimpleEvilEventLoop())
1106-
return object.__getattribute__(self, name)
1107-
1108-
evil_loop = EvilEventLoop()
1109-
with mock.patch.object(self, 'loop', evil_loop):
1110-
fut = self._new_future()
1111-
self.assertIs(fut.get_loop(), evil_loop)
1112-
1113-
fut_callback_0 = mock.Mock()
1114-
fut_context_0 = mock.Mock()
1115-
fut.add_done_callback(fut_callback_0, context=fut_context_0)
1116-
del fut_context_0
1117-
del fut_callback_0
1118-
self.assertRaises(ReachableCode, fut.set_result, "boom")
1119-
1120-
11211094
@unittest.skipUnless(hasattr(futures, '_CFuture'),
11221095
'requires the C _asyncio module')
11231096
class CFutureDoneCallbackTests(BaseFutureDoneCallbackTests,

Lib/test/test_asyncio/test_tasks.py

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2776,29 +2776,6 @@ def test_get_context(self):
27762776
finally:
27772777
loop.close()
27782778

2779-
def test_proper_refcounts(self):
2780-
# see: https://github.com/python/cpython/issues/126083
2781-
class Break:
2782-
def __str__(self):
2783-
raise RuntimeError("break")
2784-
2785-
obj = object()
2786-
initial_refcount = sys.getrefcount(obj)
2787-
2788-
coro = coroutine_function()
2789-
with contextlib.closing(asyncio.EventLoop()) as loop:
2790-
task = asyncio.Task.__new__(asyncio.Task)
2791-
for _ in range(5):
2792-
with self.assertRaisesRegex(RuntimeError, 'break'):
2793-
task.__init__(coro, loop=loop, context=obj, name=Break())
2794-
2795-
coro.close()
2796-
task._log_destroy_pending = False
2797-
del task
2798-
2799-
self.assertEqual(sys.getrefcount(obj), initial_refcount)
2800-
2801-
28022779
def add_subclass_tests(cls):
28032780
BaseTask = cls.Task
28042781
BaseFuture = cls.Future
@@ -2921,19 +2898,6 @@ class CTask_CFuture_Tests(BaseTaskTests, SetMethodsTest,
29212898
all_tasks = getattr(tasks, '_c_all_tasks', None)
29222899
current_task = staticmethod(getattr(tasks, '_c_current_task', None))
29232900

2924-
@support.refcount_test
2925-
def test_refleaks_in_task___init__(self):
2926-
gettotalrefcount = support.get_attribute(sys, 'gettotalrefcount')
2927-
async def coro():
2928-
pass
2929-
task = self.new_task(self.loop, coro())
2930-
self.loop.run_until_complete(task)
2931-
refs_before = gettotalrefcount()
2932-
for i in range(100):
2933-
task.__init__(coro(), loop=self.loop)
2934-
self.loop.run_until_complete(task)
2935-
self.assertAlmostEqual(gettotalrefcount() - refs_before, 0, delta=10)
2936-
29372901
def test_del__log_destroy_pending_segfault(self):
29382902
async def coro():
29392903
pass

Modules/_asynciomodule.c

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -498,21 +498,14 @@ future_schedule_callbacks(asyncio_state *state, FutureObj *fut)
498498
static int
499499
future_init(FutureObj *fut, PyObject *loop)
500500
{
501+
if (fut->fut_loop != NULL) {
502+
PyErr_Format(PyExc_RuntimeError,
503+
"%T object is already initialized", fut);
504+
return -1;
505+
}
506+
501507
PyObject *res;
502508
int is_true;
503-
504-
Py_CLEAR(fut->fut_loop);
505-
Py_CLEAR(fut->fut_callback0);
506-
Py_CLEAR(fut->fut_context0);
507-
Py_CLEAR(fut->fut_callbacks);
508-
Py_CLEAR(fut->fut_result);
509-
Py_CLEAR(fut->fut_exception);
510-
Py_CLEAR(fut->fut_exception_tb);
511-
Py_CLEAR(fut->fut_source_tb);
512-
Py_CLEAR(fut->fut_cancel_msg);
513-
Py_CLEAR(fut->fut_cancelled_exc);
514-
Py_CLEAR(fut->fut_awaited_by);
515-
516509
fut->fut_state = STATE_PENDING;
517510
fut->fut_log_tb = 0;
518511
fut->fut_blocking = 0;

0 commit comments

Comments
 (0)