diff options
author | dgelessus <dgelessus@users.noreply.github.com> | 2023-01-09 10:13:04 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-01-09 10:13:04 (GMT) |
commit | 837ba052672d1a5f85a46c1b6d4b6e7d192af6f3 (patch) | |
tree | cd0869c5b13a7fc35add579ac8b11f48554c23ae | |
parent | 4e544eafcb603babe0db01270bd1c6d5d0f5d6ea (diff) | |
download | cpython-837ba052672d1a5f85a46c1b6d4b6e7d192af6f3.zip cpython-837ba052672d1a5f85a46c1b6d4b6e7d192af6f3.tar.gz cpython-837ba052672d1a5f85a46c1b6d4b6e7d192af6f3.tar.bz2 |
GH-81061: Fix refcount issue when returning `None` from a `ctypes.py_object` callback (#13364)
-rw-r--r-- | Lib/test/test_ctypes/test_refcounts.py | 15 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Library/2019-05-13-11-37-30.bpo-36880.ZgBgH0.rst | 2 | ||||
-rw-r--r-- | Modules/_ctypes/callbacks.c | 15 |
3 files changed, 24 insertions, 8 deletions
diff --git a/Lib/test/test_ctypes/test_refcounts.py b/Lib/test/test_ctypes/test_refcounts.py index f2edfa6..48958cd 100644 --- a/Lib/test/test_ctypes/test_refcounts.py +++ b/Lib/test/test_ctypes/test_refcounts.py @@ -97,5 +97,20 @@ class AnotherLeak(unittest.TestCase): f(1, 2) self.assertEqual(sys.getrefcount(ctypes.c_int), a) + @support.refcount_test + def test_callback_py_object_none_return(self): + # bpo-36880: test that returning None from a py_object callback + # does not decrement the refcount of None. + + for FUNCTYPE in (ctypes.CFUNCTYPE, ctypes.PYFUNCTYPE): + with self.subTest(FUNCTYPE=FUNCTYPE): + @FUNCTYPE(ctypes.py_object) + def func(): + return None + + # Check that calling func does not affect None's refcount. + for _ in range(10000): + func() + if __name__ == '__main__': unittest.main() diff --git a/Misc/NEWS.d/next/Library/2019-05-13-11-37-30.bpo-36880.ZgBgH0.rst b/Misc/NEWS.d/next/Library/2019-05-13-11-37-30.bpo-36880.ZgBgH0.rst new file mode 100644 index 0000000..f653238 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-05-13-11-37-30.bpo-36880.ZgBgH0.rst @@ -0,0 +1,2 @@ +Fix a reference counting issue when a :mod:`ctypes` callback with return +type :class:`~ctypes.py_object` returns ``None``, which could cause crashes. diff --git a/Modules/_ctypes/callbacks.c b/Modules/_ctypes/callbacks.c index f688088..bc87500 100644 --- a/Modules/_ctypes/callbacks.c +++ b/Modules/_ctypes/callbacks.c @@ -275,15 +275,14 @@ static void _CallPythonObject(void *mem, "of ctypes callback function", callable); } - else if (keep == Py_None) { - /* Nothing to keep */ - Py_DECREF(keep); - } else if (setfunc != _ctypes_get_fielddesc("O")->setfunc) { - if (-1 == PyErr_WarnEx(PyExc_RuntimeWarning, - "memory leak in callback function.", - 1)) - { + if (keep == Py_None) { + /* Nothing to keep */ + Py_DECREF(keep); + } + else if (PyErr_WarnEx(PyExc_RuntimeWarning, + "memory leak in callback function.", + 1) == -1) { _PyErr_WriteUnraisableMsg("on converting result " "of ctypes callback function", callable); |