8000 GH-132417: ctypes: Fix potential Py_DECREF(NULL) in py_object handlin… · python/cpython@6658aea · GitHub
[go: up one dir, main page]

Skip to content

Commit 6658aea

Browse files
committed
GH-132417: ctypes: Fix potential Py_DECREF(NULL) in py_object handling (GH-132418)
1 parent deda47d commit 6658aea

File tree

2 files changed

+21
-3
lines changed

2 files changed

+21
-3
lines changed

Lib/test/test_ctypes/test_refcounts.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,5 +123,22 @@ def test_finalize(self):
123123
script_helper.assert_python_ok("-c", script)
124124

125125

126+
class PyObjectRestypeTest(unittest.TestCase):
127+
def test_restype_py_object_with_null_return(self):
128+
# We need a function which returns a PyObject *, and returns NULL,
129+
# without setting an exception.
130+
# PyErr_Occurred is one such function (when no exception is set).
131+
PyErr_Occurred = ctypes.pythonapi.PyErr_Occurred
132+
133+
PyErr_Occurred.argtypes = []
134+
PyErr_Occurred.restype = ctypes.py_object
135+
136+
# At this point, there's no exception set, so PyErr_Occurred
137+
# returns NULL. Given the restype is py_object, the
138+
# ctypes machinery will raise a custom error.
139+
with self.assertRaisesRegex(ValueError, "PyObject is NULL"):
140+
PyErr_Occurred()
141+
142+
126143
if __name__ == '__main__':
127144
unittest.main()

Modules/_ctypes/callproc.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1022,11 +1022,12 @@ static PyObject *GetResult(ctypes_state *st,
10221022
if (info->getfunc && !_ctypes_simple_instance(st, restype)) {
10231023
retval = info->getfunc(result, info->size);
10241024
/* If restype is py_object (detected by comparing getfunc with
1025-
O_get), we have to call Py_DECREF because O_get has already
1026-
called Py_INCREF.
1025+
O_get), we have to call Py_XDECREF because O_get has already
1026+
called Py_INCREF, unless the result was NULL, in which case
1027+
an error is set (by the called function, or by O_get).
10271028
*/
10281029
if (info->getfunc == _ctypes_get_fielddesc("O")->getfunc) {
1029-
Py_DECREF(retval);
1030+
Py_XDECREF(retval);
10301031
}
10311032
}
10321033
else {

0 commit comments

Comments
 (0)
0