GH-81061: Fix refcount issue when returning None from a ctypes.py_object callback (#13364)

This commit is contained in:
dgelessus 2023-01-09 11:13:04 +01:00 committed by GitHub
parent 4e544eafcb
commit 837ba05267
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 24 additions and 8 deletions

View File

@ -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()

View File

@ -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.

View File

@ -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);