bpo-30828: Fix out of bounds write in `asyncio.CFuture.remove_done_callback() (#2569)

This commit is contained in:
Yury Selivanov 2017-07-05 13:32:03 -04:00 committed by GitHub
parent 8207c17486
commit 833a3b0d37
3 changed files with 34 additions and 4 deletions

View File

@ -593,7 +593,7 @@ class BaseFutureDoneCallbackTests():
fut.remove_done_callback(evil())
def test_schedule_callbacks_list_mutation(self):
def test_schedule_callbacks_list_mutation_1(self):
# see http://bugs.python.org/issue28963 for details
def mut(f):
@ -606,6 +606,28 @@ class BaseFutureDoneCallbackTests():
fut.set_result(1)
test_utils.run_briefly(self.loop)
def test_schedule_callbacks_list_mutation_2(self):
# see http://bugs.python.org/issue30828 for details
fut = self._new_future()
fut.add_done_callback(str)
for _ in range(63):
fut.add_done_callback(id)
max_extra_cbs = 100
extra_cbs = 0
class evil:
def __eq__(self, other):
nonlocal extra_cbs
extra_cbs += 1
if extra_cbs < max_extra_cbs:
fut.add_done_callback(id)
return False
fut.remove_done_callback(evil())
@unittest.skipUnless(hasattr(futures, '_CFuture'),
'requires the C _asyncio module')

View File

@ -0,0 +1 @@
Fix out of bounds write in `asyncio.CFuture.remove_done_callback()`.

View File

@ -532,10 +532,17 @@ _asyncio_Future_remove_done_callback(FutureObj *self, PyObject *fn)
goto fail;
}
if (ret == 0) {
if (j < len) {
Py_INCREF(item);
PyList_SET_ITEM(newlist, j, item);
j++;
}
else {
if (PyList_Append(newlist, item)) {
goto fail;
}
}
}
}
if (PyList_SetSlice(newlist, j, len, NULL) < 0) {