]> granicus.if.org Git - python/commitdiff
bpo-28963: Fix out of bound iteration in asyncio.Future.remove_done_callback/C (...
authorYury Selivanov <yselivanov@gmail.com>
Fri, 3 Mar 2017 04:46:56 +0000 (23:46 -0500)
committerYury Selivanov <yury@magic.io>
Fri, 3 Mar 2017 05:05:22 +0000 (00:05 -0500)
Lib/test/test_asyncio/test_futures.py
Misc/NEWS
Modules/_asynciomodule.c

index 89afdcaff2866589d16f85bd958c23c436036c47..99336f86ab824ebe80cde2fd90587136e0bdda44 100644 (file)
@@ -569,6 +569,35 @@ class BaseFutureDoneCallbackTests():
         self.assertEqual(bag, [2])
         self.assertEqual(f.result(), 'foo')
 
+    def test_remove_done_callbacks_list_mutation(self):
+        # see http://bugs.python.org/issue28963 for details
+
+        fut = self._new_future()
+        fut.add_done_callback(str)
+
+        for _ in range(63):
+            fut.add_done_callback(id)
+
+        class evil:
+            def __eq__(self, other):
+                fut.remove_done_callback(id)
+                return False
+
+        fut.remove_done_callback(evil())
+
+    def test_schedule_callbacks_list_mutation(self):
+        # see http://bugs.python.org/issue28963 for details
+
+        def mut(f):
+            f.remove_done_callback(str)
+
+        fut = self._new_future()
+        fut.add_done_callback(mut)
+        fut.add_done_callback(str)
+        fut.add_done_callback(str)
+        fut.set_result(1)
+        test_utils.run_briefly(self.loop)
+
 
 @unittest.skipUnless(hasattr(futures, '_CFuture'),
                      'requires the C _asyncio module')
index ef45957e47e76ca98f77bbb8e4f62ca852214f18..a13d8c74f23228c3bd61a7e7409f0380f646a282 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -261,6 +261,9 @@ Extension Modules
 Library
 -------
 
+- bpo-28963: Fix out of bound iteration in asyncio.Future.remove_done_callback
+  implemented in C.
+
 - bpo-29704: asyncio.subprocess.SubprocessStreamProtocol no longer closes before
   all pipes are closed.
 
index d0e43ae47d9ec824b0ff0f0186ea2a4c636f5a30..a77ff9689e4705e64d608bcacd4b32aae473f202 100644 (file)
@@ -521,7 +521,7 @@ _asyncio_Future_remove_done_callback(FutureObj *self, PyObject *fn)
         return NULL;
     }
 
-    for (i = 0; i < len; i++) {
+    for (i = 0; i < PyList_GET_SIZE(self->fut_callbacks); i++) {
         int ret;
         PyObject *item = PyList_GET_ITEM(self->fut_callbacks, i);