Skip to content

Commit 837ba05

Browse files
authored
GH-81061: Fix refcount issue when returning None from a ctypes.py_object callback (#13364)
1 parent 4e544ea commit 837ba05

File tree

3 files changed

+24
-8
lines changed

3 files changed

+24
-8
lines changed

Lib/test/test_ctypes/test_refcounts.py

+15
Original file line numberDiff line numberDiff line change
@@ -97,5 +97,20 @@ def func(a, b):
9797
f(1, 2)
9898
self.assertEqual(sys.getrefcount(ctypes.c_int), a)
9999

100+
@support.refcount_test
101+
def test_callback_py_object_none_return(self):
102+
# bpo-36880: test that returning None from a py_object callback
103+
# does not decrement the refcount of None.
104+
105+
for FUNCTYPE in (ctypes.CFUNCTYPE, ctypes.PYFUNCTYPE):
106+
with self.subTest(FUNCTYPE=FUNCTYPE):
107+
@FUNCTYPE(ctypes.py_object)
108+
def func():
109+
return None
110+
111+
# Check that calling func does not affect None's refcount.
112+
for _ in range(10000):
113+
func()
114+
100115
if __name__ == '__main__':
101116
unittest.main()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix a reference counting issue when a :mod:`ctypes` callback with return
2+
type :class:`~ctypes.py_object` returns ``None``, which could cause crashes.

Modules/_ctypes/callbacks.c

+7-8
Original file line numberDiff line numberDiff line change
@@ -275,15 +275,14 @@ static void _CallPythonObject(void *mem,
275275
"of ctypes callback function",
276276
callable);
277277
}
278-
else if (keep == Py_None) {
279-
/* Nothing to keep */
280-
Py_DECREF(keep);
281-
}
282278
else if (setfunc != _ctypes_get_fielddesc("O")->setfunc) {
283-
if (-1 == PyErr_WarnEx(PyExc_RuntimeWarning,
284-
"memory leak in callback function.",
285-
1))
286-
{
279+
if (keep == Py_None) {
280+
/* Nothing to keep */
281+
Py_DECREF(keep);
282+
}
283+
else if (PyErr_WarnEx(PyExc_RuntimeWarning,
284+
"memory leak in callback function.",
285+
1) == -1) {
287286
_PyErr_WriteUnraisableMsg("on converting result "
288287
"of ctypes callback function",
289288
callable);

0 commit comments

Comments
 (0)