From a4f84682eda391e1a2bc3e64c7c0c6028ed2457b Mon Sep 17 00:00:00 2001 From: Sergey Miryanov Date: Sun, 16 Mar 2025 02:01:39 +0500 Subject: [PATCH 1/2] Fix memory leak in PyCStructUnionType_update_stginfo --- Modules/_ctypes/stgdict.c | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/_ctypes/stgdict.c b/Modules/_ctypes/stgdict.c index 05239d85c44d2c..7c794d42cd5a76 100644 --- a/Modules/_ctypes/stgdict.c +++ b/Modules/_ctypes/stgdict.c @@ -267,6 +267,7 @@ PyCStructUnionType_update_stginfo(PyObject *type, PyObject *fields, int isStruct &_Py_ID(is_struct), &_Py_ID(base)); if (!kwnames) { + Py_DECREF(layout_func); goto error; } layout = PyObject_Vectorcall( From d978ab5d283d7a0635211174cff6cdf8289674e5 Mon Sep 17 00:00:00 2001 From: Sergey Miryanov Date: Mon, 17 Mar 2025 23:53:29 +0500 Subject: [PATCH 2/2] Move cleanup of locals to error section --- Modules/_ctypes/stgdict.c | 41 +++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/Modules/_ctypes/stgdict.c b/Modules/_ctypes/stgdict.c index 7c794d42cd5a76..107716d85fed2d 100644 --- a/Modules/_ctypes/stgdict.c +++ b/Modules/_ctypes/stgdict.c @@ -217,13 +217,17 @@ MakeAnonFields(PyObject *type) int PyCStructUnionType_update_stginfo(PyObject *type, PyObject *fields, int isStruct) { - PyObject *tmp; Py_ssize_t ffi_ofs; int arrays_seen = 0; int retval = -1; // The following are NULL or hold strong references. // 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 = NULL; PyObject *format_spec_obj = NULL; @@ -257,17 +261,15 @@ PyCStructUnionType_update_stginfo(PyObject *type, PyObject *fields, int isStruct goto error; } - PyObject *layout_func = PyImport_ImportModuleAttrString("ctypes._layout", - "get_layout"); + layout_func = PyImport_ImportModuleAttrString("ctypes._layout", "get_layout"); if (!layout_func) { goto error; } - PyObject *kwnames = PyTuple_Pack( + kwnames = PyTuple_Pack( 2, &_Py_ID(is_struct), &_Py_ID(base)); if (!kwnames) { - Py_DECREF(layout_func); goto error; } layout = PyObject_Vectorcall( @@ -282,19 +284,19 @@ PyCStructUnionType_update_stginfo(PyObject *type, PyObject *fields, int isStruct baseinfo ? base : Py_None}, 2 | PY_VECTORCALL_ARGUMENTS_OFFSET, kwnames); - Py_DECREF(kwnames); - Py_DECREF(layout_func); + Py_CLEAR(kwnames); + Py_CLEAR(layout_func); fields = NULL; // a borrowed reference we won't be using again if (!layout) { goto error; } - tmp = PyObject_GetAttr(layout, &_Py_ID(align)); - if (!tmp) { + align = PyObject_GetAttr(layout, &_Py_ID(align)); + if (!align) { goto error; } - Py_ssize_t total_align = PyLong_AsSsize_t(tmp); - Py_DECREF(tmp); + Py_ssize_t total_align = PyLong_AsSsize_t(align); + Py_CLEAR(align); if (total_align < 0) { if (!PyErr_Occurred()) { PyErr_SetString(PyExc_ValueError, @@ -303,12 +305,12 @@ PyCStructUnionType_update_stginfo(PyObject *type, PyObject *fields, int isStruct goto error; } - tmp = PyObject_GetAttr(layout, &_Py_ID(size)); - if (!tmp) { + size = PyObject_GetAttr(layout, &_Py_ID(size)); + if (!size) { goto error; } - Py_ssize_t total_size = PyLong_AsSsize_t(tmp); - Py_DECREF(tmp); + Py_ssize_t total_size = PyLong_AsSsize_t(size); + Py_CLEAR(size); if (total_size < 0) { if (!PyErr_Occurred()) { PyErr_SetString(PyExc_ValueError, @@ -339,15 +341,15 @@ PyCStructUnionType_update_stginfo(PyObject *type, PyObject *fields, int isStruct } 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) { goto error; } layout_fields = PySequence_Tuple(layout_fields_obj); - Py_DECREF(layout_fields_obj); if (!layout_fields) { goto error; } + Py_CLEAR(layout_fields_obj); Py_CLEAR(layout); Py_ssize_t len = PyTuple_GET_SIZE(layout_fields); @@ -665,6 +667,11 @@ PyCStructUnionType_update_stginfo(PyObject *type, PyObject *fields, int isStruct retval = MakeAnonFields(type); 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); Py_XDECREF(format_spec_obj);