Skip to content

Commit

Permalink
pythonGH-81061: Fix refcount issue when returning None from a `ctyp…
Browse files Browse the repository at this point in the history
…es.py_object` callback (pythonGH-13364)

(cherry picked from commit 837ba05)

Co-authored-by: dgelessus <dgelessus@users.noreply.github.com>
  • Loading branch information
dgelessus authored and miss-islington committed Jan 9, 2023
1 parent 074b881 commit 496bdb8
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 8 deletions.
15 changes: 15 additions & 0 deletions Lib/ctypes/test/test_refcounts.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,5 +97,20 @@ def func(a, b):
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()
Original file line number Diff line number Diff line change
@@ -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.
15 changes: 7 additions & 8 deletions Modules/_ctypes/callbacks.c
Original file line number Diff line number Diff line change
Expand Up @@ -276,15 +276,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);
Expand Down

0 comments on commit 496bdb8

Please sign in to comment.