Merge remote-tracking branch 'upstream/master' into memleak
# Conflicts:
# CHANGES.current
diff --git a/CHANGES.current b/CHANGES.current
index 4eee6b2..d82cde7 100644
--- a/CHANGES.current
+++ b/CHANGES.current
@@ -7,6 +7,32 @@
Version 4.1.0 (in progress)
===========================
+2021-05-17: adr26
+ [Python] #1985 Fix memory leaks:
+
+ 1. Python object references were being incorrectly retained by
+ SwigPyClientData, causing swig_varlink_dealloc() never to run / free
+ memory. SwigPyClientData_New() / SwigPyClientData_Del() were updated
+ to fix the object reference counting, causing swig_varlink_dealloc()
+ to run and the memory swig_varlink owns to be freed.
+
+ 2. SwigPyClientData itself was not freed by SwigPyClientData_Del(),
+ causing another heap leak. The required free() was added to
+ SwigPyClientData_Del()
+
+ 3. Fix reference counting/leak of python cached type query
+
+ 4. Fix reference counting/leak of SwigPyObject dict (-builtin)
+
+ 5. Python object reference counting fixes for out-of-memory
+ scenarios were added to: SWIG_Python_RaiseOrModifyTypeError(),
+ SWIG_Python_AppendOutput(), SwigPyClientData_New(),
+ SwigPyObject_get___dict__() and SwigPyObject_format()
+
+ 6. Add error handling for PyModule_AddObject() to
+ SWIG_Python_SetModule() (failure could be caused by OOM or a name
+ clash caused by malicious code)
+
2021-05-13: olly
[UFFI] #2009 Remove code for Common Lisp UFFI. We dropped support
for it in SWIG 4.0.0 and nobody has stepped forward to revive it in
diff --git a/Lib/python/pyerrors.swg b/Lib/python/pyerrors.swg
index dcd99c9..2628de8 100644
--- a/Lib/python/pyerrors.swg
+++ b/Lib/python/pyerrors.swg
@@ -95,8 +95,12 @@
#else
newvalue = PyString_FromFormat("%s\nAdditional information:\n%s", PyString_AsString(value), message);
#endif
- Py_XDECREF(value);
- PyErr_Restore(type, newvalue, traceback);
+ if (newvalue) {
+ Py_XDECREF(value);
+ PyErr_Restore(type, newvalue, traceback);
+ } else {
+ PyErr_Restore(type, value, traceback);
+ }
} else {
/* Raise TypeError using given message */
PyErr_SetString(PyExc_TypeError, message);
diff --git a/Lib/python/pyrun.swg b/Lib/python/pyrun.swg
index 63ff82f..f32afb0 100644
--- a/Lib/python/pyrun.swg
+++ b/Lib/python/pyrun.swg
@@ -127,7 +127,11 @@
if (!PyList_Check(result)) {
PyObject *o2 = result;
result = PyList_New(1);
- PyList_SetItem(result, 0, o2);
+ if (result) {
+ PyList_SET_ITEM(result, 0, o2);
+ } else {
+ return o2;
+ }
}
PyList_Append(result,obj);
Py_DECREF(obj);
@@ -279,18 +283,26 @@
/* the newraw method and newargs arguments used to create a new raw instance */
if (PyClass_Check(obj)) {
data->newraw = 0;
- data->newargs = obj;
Py_INCREF(obj);
+ data->newargs = obj;
} else {
data->newraw = PyObject_GetAttrString(data->klass, "__new__");
if (data->newraw) {
- Py_INCREF(data->newraw);
- data->newargs = PyTuple_New(1);
- PyTuple_SetItem(data->newargs, 0, obj);
+ data->newargs = PyTuple_New(1);
+ if (data->newargs) {
+ Py_INCREF(obj);
+ PyTuple_SET_ITEM(data->newargs, 0, obj);
+ } else {
+ Py_DECREF(data->newraw);
+ Py_DECREF(data->klass);
+ free(data);
+ PyErr_NoMemory();
+ return 0;
+ }
} else {
- data->newargs = obj;
+ Py_INCREF(obj);
+ data->newargs = obj;
}
- Py_INCREF(data->newargs);
}
/* the destroy method, aka as the C++ delete method */
data->destroy = PyObject_GetAttrString(data->klass, "__swig_destroy__");
@@ -299,10 +311,7 @@
data->destroy = 0;
}
if (data->destroy) {
- int flags;
- Py_INCREF(data->destroy);
- flags = PyCFunction_GET_FLAGS(data->destroy);
- data->delargs = !(flags & (METH_O));
+ data->delargs = !(PyCFunction_GET_FLAGS(data->destroy) & METH_O);
} else {
data->delargs = 0;
}
@@ -313,10 +322,13 @@
}
SWIGRUNTIME void
-SwigPyClientData_Del(SwigPyClientData *data) {
+SwigPyClientData_Del(SwigPyClientData *data)
+{
+ Py_XDECREF(data->klass);
Py_XDECREF(data->newraw);
Py_XDECREF(data->newargs);
Py_XDECREF(data->destroy);
+ free(data);
}
/* =============== SwigPyObject =====================*/
@@ -343,6 +355,9 @@
if (!sobj->dict)
sobj->dict = PyDict_New();
+ if (!sobj->dict)
+ return PyErr_NoMemory();
+
Py_INCREF(sobj->dict);
return sobj->dict;
}
@@ -361,18 +376,21 @@
PyObject *res = NULL;
PyObject *args = PyTuple_New(1);
if (args) {
- if (PyTuple_SetItem(args, 0, SwigPyObject_long(v)) == 0) {
- PyObject *ofmt = SWIG_Python_str_FromChar(fmt);
+ PyObject *val = SwigPyObject_long(v);
+ if (val) {
+ PyObject *ofmt;
+ PyTuple_SET_ITEM(args, 0, val);
+ ofmt = SWIG_Python_str_FromChar(fmt);
if (ofmt) {
#if PY_VERSION_HEX >= 0x03000000
- res = PyUnicode_Format(ofmt,args);
+ res = PyUnicode_Format(ofmt,args);
#else
- res = PyString_Format(ofmt,args);
+ res = PyString_Format(ofmt,args);
#endif
- Py_DECREF(ofmt);
+ Py_DECREF(ofmt);
}
- Py_DECREF(args);
}
+ Py_DECREF(args);
}
return res;
}
@@ -523,6 +541,9 @@
#endif
}
Py_XDECREF(next);
+#ifdef SWIGPYTHON_BUILTIN
+ Py_XDECREF(sobj->dict);
+#endif
PyObject_DEL(v);
}
@@ -582,6 +603,7 @@
} else {
SwigPyObject_disown(v,args);
}
+ Py_DECREF(Py_None);
}
return obj;
}
@@ -740,6 +762,9 @@
sobj->ty = ty;
sobj->own = own;
sobj->next = 0;
+#ifdef SWIGPYTHON_BUILTIN
+ sobj->dict = 0;
+#endif
}
return (PyObject *)sobj;
}
@@ -1310,7 +1335,9 @@
} else {
newobj = PyObject_New(SwigPyObject, clientdata->pytype);
#ifdef SWIGPYTHON_BUILTIN
- newobj->dict = 0;
+ if (newobj) {
+ newobj->dict = 0;
+ }
#endif
}
if (newobj) {
@@ -1349,6 +1376,13 @@
void *SWIG_ReturnGlobalTypeList(void *);
#endif
+/* The python cached type query */
+SWIGRUNTIME PyObject *
+SWIG_Python_TypeCache(void) {
+ static PyObject *SWIG_STATIC_POINTER(cache) = PyDict_New();
+ return cache;
+}
+
SWIGRUNTIME swig_module_info *
SWIG_Python_GetModule(void *SWIGUNUSEDPARM(clientdata)) {
static void *type_pointer = (void *)0;
@@ -1377,11 +1411,13 @@
swig_type_info *ty = types[i];
if (ty->owndata) {
SwigPyClientData *data = (SwigPyClientData *) ty->clientdata;
+ ty->clientdata = 0;
if (data) SwigPyClientData_Del(data);
}
}
Py_DECREF(SWIG_This());
Swig_This_global = NULL;
+ Py_DECREF(SWIG_Python_TypeCache());
}
SWIGRUNTIME void
@@ -1395,19 +1431,14 @@
#endif
PyObject *pointer = PyCapsule_New((void *) swig_module, SWIGPY_CAPSULE_NAME, SWIG_Python_DestroyModule);
if (pointer && module) {
- PyModule_AddObject(module, "type_pointer_capsule" SWIG_TYPE_TABLE_NAME, pointer);
+ if (PyModule_AddObject(module, "type_pointer_capsule" SWIG_TYPE_TABLE_NAME, pointer) < 0) {
+ Py_DECREF(pointer);
+ }
} else {
Py_XDECREF(pointer);
}
}
-/* The python cached type query */
-SWIGRUNTIME PyObject *
-SWIG_Python_TypeCache(void) {
- static PyObject *SWIG_STATIC_POINTER(cache) = PyDict_New();
- return cache;
-}
-
SWIGRUNTIME swig_type_info *
SWIG_Python_TypeQuery(const char *type)
{