gh-131311: Consolidate reference handling in PyCStructUnionType_update_stginfo to fix memory leak (GH-131312)

This commit is contained in:
Sergey Miryanov 2025-03-18 15:50:22 +05:00 committed by GitHub
parent 3453b5c1d6
commit 812074e291
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -217,13 +217,17 @@ MakeAnonFields(PyObject *type)
int int
PyCStructUnionType_update_stginfo(PyObject *type, PyObject *fields, int isStruct) PyCStructUnionType_update_stginfo(PyObject *type, PyObject *fields, int isStruct)
{ {
PyObject *tmp;
Py_ssize_t ffi_ofs; Py_ssize_t ffi_ofs;
int arrays_seen = 0; int arrays_seen = 0;
int retval = -1; int retval = -1;
// The following are NULL or hold strong references. // The following are NULL or hold strong references.
// They're cleared on error. // They're cleared on error.
PyObject *layout_func = NULL;
PyObject *kwnames = NULL;
PyObject* align = NULL;
PyObject* size = NULL;
PyObject *layout_fields_obj = NULL;
PyObject *layout_fields = NULL; PyObject *layout_fields = NULL;
PyObject *layout = NULL; PyObject *layout = NULL;
PyObject *format_spec_obj = NULL; PyObject *format_spec_obj = NULL;
@ -257,12 +261,11 @@ PyCStructUnionType_update_stginfo(PyObject *type, PyObject *fields, int isStruct
goto error; goto error;
} }
PyObject *layout_func = PyImport_ImportModuleAttrString("ctypes._layout", layout_func = PyImport_ImportModuleAttrString("ctypes._layout", "get_layout");
"get_layout");
if (!layout_func) { if (!layout_func) {
goto error; goto error;
} }
PyObject *kwnames = PyTuple_Pack( kwnames = PyTuple_Pack(
2, 2,
&_Py_ID(is_struct), &_Py_ID(is_struct),
&_Py_ID(base)); &_Py_ID(base));
@ -281,19 +284,19 @@ PyCStructUnionType_update_stginfo(PyObject *type, PyObject *fields, int isStruct
baseinfo ? base : Py_None}, baseinfo ? base : Py_None},
2 | PY_VECTORCALL_ARGUMENTS_OFFSET, 2 | PY_VECTORCALL_ARGUMENTS_OFFSET,
kwnames); kwnames);
Py_DECREF(kwnames); Py_CLEAR(kwnames);
Py_DECREF(layout_func); Py_CLEAR(layout_func);
fields = NULL; // a borrowed reference we won't be using again fields = NULL; // a borrowed reference we won't be using again
if (!layout) { if (!layout) {
goto error; goto error;
} }
tmp = PyObject_GetAttr(layout, &_Py_ID(align)); align = PyObject_GetAttr(layout, &_Py_ID(align));
if (!tmp) { if (!align) {
goto error; goto error;
} }
Py_ssize_t total_align = PyLong_AsSsize_t(tmp); Py_ssize_t total_align = PyLong_AsSsize_t(align);
Py_DECREF(tmp); Py_CLEAR(align);
if (total_align < 0) { if (total_align < 0) {
if (!PyErr_Occurred()) { if (!PyErr_Occurred()) {
PyErr_SetString(PyExc_ValueError, PyErr_SetString(PyExc_ValueError,
@ -302,12 +305,12 @@ PyCStructUnionType_update_stginfo(PyObject *type, PyObject *fields, int isStruct
goto error; goto error;
} }
tmp = PyObject_GetAttr(layout, &_Py_ID(size)); size = PyObject_GetAttr(layout, &_Py_ID(size));
if (!tmp) { if (!size) {
goto error; goto error;
} }
Py_ssize_t total_size = PyLong_AsSsize_t(tmp); Py_ssize_t total_size = PyLong_AsSsize_t(size);
Py_DECREF(tmp); Py_CLEAR(size);
if (total_size < 0) { if (total_size < 0) {
if (!PyErr_Occurred()) { if (!PyErr_Occurred()) {
PyErr_SetString(PyExc_ValueError, PyErr_SetString(PyExc_ValueError,
@ -338,15 +341,15 @@ PyCStructUnionType_update_stginfo(PyObject *type, PyObject *fields, int isStruct
} }
memcpy(stginfo->format, format_spec, format_spec_size + 1); memcpy(stginfo->format, format_spec, format_spec_size + 1);
PyObject *layout_fields_obj = PyObject_GetAttr(layout, &_Py_ID(fields)); layout_fields_obj = PyObject_GetAttr(layout, &_Py_ID(fields));
if (!layout_fields_obj) { if (!layout_fields_obj) {
goto error; goto error;
} }
layout_fields = PySequence_Tuple(layout_fields_obj); layout_fields = PySequence_Tuple(layout_fields_obj);
Py_DECREF(layout_fields_obj);
if (!layout_fields) { if (!layout_fields) {
goto error; goto error;
} }
Py_CLEAR(layout_fields_obj);
Py_CLEAR(layout); Py_CLEAR(layout);
Py_ssize_t len = PyTuple_GET_SIZE(layout_fields); Py_ssize_t len = PyTuple_GET_SIZE(layout_fields);
@ -664,6 +667,11 @@ PyCStructUnionType_update_stginfo(PyObject *type, PyObject *fields, int isStruct
retval = MakeAnonFields(type); retval = MakeAnonFields(type);
error: error:
Py_XDECREF(layout_func);
Py_XDECREF(kwnames);
Py_XDECREF(align);
Py_XDECREF(size);
Py_XDECREF(layout_fields_obj);
Py_XDECREF(layout_fields); Py_XDECREF(layout_fields);
Py_XDECREF(layout); Py_XDECREF(layout);
Py_XDECREF(format_spec_obj); Py_XDECREF(format_spec_obj);