From adef6460d73ce1ab33af9c9ef014aa88f23c6d62 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Thu, 16 Jun 2016 22:08:46 +0300 Subject: Issue #27330: Fixed possible leaks in the ctypes module. --- Misc/NEWS | 2 ++ Modules/_ctypes/_ctypes.c | 25 +++++++++++++++++++------ Modules/_ctypes/callproc.c | 8 +++++++- Modules/_ctypes/cfield.c | 20 +++++--------------- 4 files changed, 33 insertions(+), 22 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS index fe847b4..66a95f7 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,8 @@ Core and Builtins Library ------- +- Issue #27330: Fixed possible leaks in the ctypes module. + - Issue #27238: Got rid of bare excepts in the turtle module. Original patch by Jelle Zijlstra. diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 2e01323..c49abf0 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -1252,8 +1252,10 @@ add_methods(PyTypeObject *type, PyMethodDef *meth) descr = PyDescr_NewMethod(type, meth); if (descr == NULL) return -1; - if (PyDict_SetItemString(dict,meth->ml_name, descr) < 0) + if (PyDict_SetItemString(dict, meth->ml_name, descr) < 0) { + Py_DECREF(descr); return -1; + } Py_DECREF(descr); } return 0; @@ -1268,8 +1270,10 @@ add_members(PyTypeObject *type, PyMemberDef *memb) descr = PyDescr_NewMember(type, memb); if (descr == NULL) return -1; - if (PyDict_SetItemString(dict, memb->name, descr) < 0) + if (PyDict_SetItemString(dict, memb->name, descr) < 0) { + Py_DECREF(descr); return -1; + } Py_DECREF(descr); } return 0; @@ -1285,8 +1289,10 @@ add_getset(PyTypeObject *type, PyGetSetDef *gsp) descr = PyDescr_NewGetSet(type, gsp); if (descr == NULL) return -1; - if (PyDict_SetItemString(dict, gsp->name, descr) < 0) + if (PyDict_SetItemString(dict, gsp->name, descr) < 0) { + Py_DECREF(descr); return -1; + } Py_DECREF(descr); } return 0; @@ -1778,6 +1784,7 @@ static PyObject *CreateSwappedType(PyTypeObject *type, PyObject *args, PyObject newname = PyUnicode_Concat(name, suffix); if (newname == NULL) { + Py_DECREF(swapped_args); return NULL; } @@ -1797,8 +1804,10 @@ static PyObject *CreateSwappedType(PyTypeObject *type, PyObject *args, PyObject stgdict = (StgDictObject *)PyObject_CallObject( (PyObject *)&PyCStgDict_Type, NULL); - if (!stgdict) /* XXX leaks result! */ + if (!stgdict) { + Py_DECREF(result); return NULL; + } stgdict->ffi_type_pointer = *fmt->pffi_type; stgdict->align = fmt->pffi_type->alignment; @@ -1978,8 +1987,10 @@ PyCSimpleType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) PyObject *meth; int x; meth = PyDescr_NewClassMethod(result, ml); - if (!meth) + if (!meth) { + Py_DECREF(result); return NULL; + } x = PyDict_SetItemString(result->tp_dict, ml->ml_name, meth); @@ -2159,8 +2170,10 @@ converters_from_argtypes(PyObject *ob) nArgs = PyTuple_GET_SIZE(ob); converters = PyTuple_New(nArgs); - if (!converters) + if (!converters) { + Py_DECREF(ob); return NULL; + } /* I have to check if this is correct. Using c_char, which has a size of 1, will be assumed to be pushed as only one byte! diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c index 03a911f..30e3a96 100644 --- a/Modules/_ctypes/callproc.c +++ b/Modules/_ctypes/callproc.c @@ -157,8 +157,10 @@ _ctypes_get_errobj(int **pspace) return NULL; memset(space, 0, sizeof(int) * 2); errobj = PyCapsule_New(space, CTYPES_CAPSULE_NAME_PYMEM, pymem_destructor); - if (errobj == NULL) + if (errobj == NULL) { + PyMem_Free(space); return NULL; + } if (-1 == PyDict_SetItem(dict, error_object_name, errobj)) { Py_DECREF(errobj); @@ -1681,6 +1683,10 @@ POINTER(PyObject *self, PyObject *cls) if (result == NULL) return result; key = PyLong_FromVoidPtr(result); + if (key == NULL) { + Py_DECREF(result); + return NULL; + } } else if (PyType_Check(cls)) { typ = (PyTypeObject *)cls; buf = PyMem_Malloc(strlen(typ->tp_name) + 3 + 1); diff --git a/Modules/_ctypes/cfield.c b/Modules/_ctypes/cfield.c index 8cb6d66..d666be5 100644 --- a/Modules/_ctypes/cfield.c +++ b/Modules/_ctypes/cfield.c @@ -1246,8 +1246,7 @@ U_set(void *ptr, PyObject *value, Py_ssize_t length) "unicode string expected instead of %s instance", value->ob_type->tp_name); return NULL; - } else - Py_INCREF(value); + } wstr = PyUnicode_AsUnicodeAndSize(value, &size); if (wstr == NULL) @@ -1256,7 +1255,6 @@ U_set(void *ptr, PyObject *value, Py_ssize_t length) PyErr_Format(PyExc_ValueError, "string too long (%zd, maximum length %zd)", size, length); - Py_DECREF(value); return NULL; } else if (size < length-1) /* copy terminating NUL character if there is space */ @@ -1266,6 +1264,7 @@ U_set(void *ptr, PyObject *value, Py_ssize_t length) return NULL; } + Py_INCREF(value); return value; } @@ -1292,9 +1291,7 @@ s_set(void *ptr, PyObject *value, Py_ssize_t length) char *data; Py_ssize_t size; - if(PyBytes_Check(value)) { - Py_INCREF(value); - } else { + if(!PyBytes_Check(value)) { PyErr_Format(PyExc_TypeError, "expected bytes, %s found", value->ob_type->tp_name); @@ -1302,11 +1299,9 @@ s_set(void *ptr, PyObject *value, Py_ssize_t length) } data = PyBytes_AS_STRING(value); - if (!data) - return NULL; size = strlen(data); /* XXX Why not Py_SIZE(value)? */ if (size < length) { - /* This will copy the leading NUL character + /* This will copy the terminating NUL character * if there is space for it. */ ++size; @@ -1314,13 +1309,11 @@ s_set(void *ptr, PyObject *value, Py_ssize_t length) PyErr_Format(PyExc_ValueError, "bytes too long (%zd, maximum length %zd)", size, length); - Py_DECREF(value); return NULL; } /* Also copy the terminating NUL character if there is space */ memcpy((char *)ptr, data, size); - Py_DECREF(value); _RET(value); } @@ -1428,9 +1421,7 @@ BSTR_set(void *ptr, PyObject *value, Py_ssize_t size) /* convert value into a PyUnicodeObject or NULL */ if (Py_None == value) { value = NULL; - } else if (PyUnicode_Check(value)) { - Py_INCREF(value); /* for the descref below */ - } else { + } else if (!PyUnicode_Check(value)) { PyErr_Format(PyExc_TypeError, "unicode string expected instead of %s instance", value->ob_type->tp_name); @@ -1449,7 +1440,6 @@ BSTR_set(void *ptr, PyObject *value, Py_ssize_t size) return NULL; } bstr = SysAllocStringLen(wvalue, (unsigned)wsize); - Py_DECREF(value); } else bstr = NULL; -- cgit v0.12