Skip to content

Commit 833a3b0

Browse files
authored
bpo-30828: Fix out of bounds write in `asyncio.CFuture.remove_done_callback() (#2569)
1 parent 8207c17 commit 833a3b0

File tree

3 files changed

+34
-4
lines changed

3 files changed

+34
-4
lines changed

Lib/test/test_asyncio/test_futures.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -593,7 +593,7 @@ def __eq__(self, other):
593593

594594
fut.remove_done_callback(evil())
595595

596-
def test_schedule_callbacks_list_mutation(self):
596+
def test_schedule_callbacks_list_mutation_1(self):
597597
# see http://bugs.python.org/issue28963 for details
598598

599599
def mut(f):
@@ -606,6 +606,28 @@ def mut(f):
606606
fut.set_result(1)
607607
test_utils.run_briefly(self.loop)
608608

609+
def test_schedule_callbacks_list_mutation_2(self):
610+
# see http://bugs.python.org/issue30828 for details
611+
612+
fut = self._new_future()
613+
fut.add_done_callback(str)
614+
615+
for _ in range(63):
616+
fut.add_done_callback(id)
617+
618+
max_extra_cbs = 100
619+
extra_cbs = 0
620+
621+
class evil:
622+
def __eq__(self, other):
623+
nonlocal extra_cbs
624+
extra_cbs += 1
625+
if extra_cbs < max_extra_cbs:
626+
fut.add_done_callback(id)
627+
return False
628+
629+
fut.remove_done_callback(evil())
630+
609631

610632
@unittest.skipUnless(hasattr(futures, '_CFuture'),
611633
'requires the C _asyncio module')
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix out of bounds write in `asyncio.CFuture.remove_done_callback()`.

Modules/_asynciomodule.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -532,9 +532,16 @@ _asyncio_Future_remove_done_callback(FutureObj *self, PyObject *fn)
532532
goto fail;
533533
}
534534
if (ret == 0) {
535-
Py_INCREF(item);
536-
PyList_SET_ITEM(newlist, j, item);
537-
j++;
535+
if (j < len) {
536+
Py_INCREF(item);
537+
PyList_SET_ITEM(newlist, j, item);
538+
j++;
539+
}
540+
else {
541+
if (PyList_Append(newlist, item)) {
542+
goto fail;
543+
}
544+
}
538545
}
539546
}
540547

0 commit comments

Comments
 (0)