Merge pull request #2019 from adr26/memleak

[Python] Fix memory leaks.
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..0025184 100644
--- a/Lib/python/pyrun.swg
+++ b/Lib/python/pyrun.swg
@@ -127,7 +127,12 @@
     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 {
+        Py_DECREF(obj);
+        return o2;
+      }
     }
     PyList_Append(result,obj);
     Py_DECREF(obj);
@@ -279,18 +284,25 @@
     /* 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);
+          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,7 +355,7 @@
   if (!sobj->dict)
     sobj->dict = PyDict_New();
 
-  Py_INCREF(sobj->dict);
+  Py_XINCREF(sobj->dict);
   return sobj->dict;
 }
 
@@ -361,18 +373,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;
 }
@@ -394,18 +409,23 @@
 {
   const char *name = SWIG_TypePrettyName(v->ty);
   PyObject *repr = SWIG_Python_str_FromFormat("<Swig Object of type '%s' at %p>", (name ? name : "unknown"), (void *)v);
-  if (v->next) {
+  if (repr && v->next) {
     PyObject *nrep = SwigPyObject_repr((SwigPyObject *)v->next);
+    if (nrep) {
 # if PY_VERSION_HEX >= 0x03000000
-    PyObject *joined = PyUnicode_Concat(repr, nrep);
-    Py_DecRef(repr);
-    Py_DecRef(nrep);
-    repr = joined;
+      PyObject *joined = PyUnicode_Concat(repr, nrep);
+      Py_DecRef(repr);
+      Py_DecRef(nrep);
+      repr = joined;
 # else
-    PyString_ConcatAndDel(&repr,nrep);
+      PyString_ConcatAndDel(&repr,nrep);
 # endif
+    } else {
+      Py_DecRef(repr);
+      repr = NULL;
+    }
   }
-  return repr;  
+  return repr;
 }
 
 /* We need a version taking two PyObject* parameters so it's a valid
@@ -501,8 +521,12 @@
       if (data->delargs) {
         /* we need to create a temporary object to carry the destroy operation */
         PyObject *tmp = SwigPyObject_New(sobj->ptr, ty, 0);
-        res = SWIG_Python_CallFunctor(destroy, tmp);
-        Py_DECREF(tmp);
+        if (tmp) {
+          res = SWIG_Python_CallFunctor(destroy, tmp);
+        } else {
+          res = 0;
+        }
+        Py_XDECREF(tmp);
       } else {
         PyCFunction meth = PyCFunction_GET_FUNCTION(destroy);
         PyObject *mself = PyCFunction_GET_SELF(destroy);
@@ -523,6 +547,9 @@
 #endif
   } 
   Py_XDECREF(next);
+#ifdef SWIGPYTHON_BUILTIN
+  Py_XDECREF(sobj->dict);
+#endif
   PyObject_DEL(v);
 }
 
@@ -578,9 +605,9 @@
     PyObject *obj = PyBool_FromLong(sobj->own);
     if (val) {
       if (PyObject_IsTrue(val)) {
-        SwigPyObject_acquire(v,args);
+        Py_DECREF(SwigPyObject_acquire(v,args));
       } else {
-        SwigPyObject_disown(v,args);
+        Py_DECREF(SwigPyObject_disown(v,args));
       }
     } 
     return obj;
@@ -725,7 +752,7 @@
     };
     swigpyobject_type = tmp;
     type_init = 1;
-    if (PyType_Ready(&swigpyobject_type) < 0)
+    if (PyType_Ready(&swigpyobject_type) != 0)
       return NULL;
   }
   return &swigpyobject_type;
@@ -740,6 +767,9 @@
     sobj->ty   = ty;
     sobj->own  = own;
     sobj->next = 0;
+#ifdef SWIGPYTHON_BUILTIN
+    sobj->dict = 0;
+#endif
   }
   return (PyObject *)sobj;
 }
@@ -892,7 +922,7 @@
     };
     swigpypacked_type = tmp;
     type_init = 1;
-    if (PyType_Ready(&swigpypacked_type) < 0)
+    if (PyType_Ready(&swigpypacked_type) != 0)
       return NULL;
   }
   return &swigpypacked_type;
@@ -1200,12 +1230,17 @@
 #if !defined(SWIG_PYTHON_SLOW_GETSET_THIS)
       PyObject **dictptr = _PyObject_GetDictPtr(inst);
       if (dictptr != NULL) {
-	PyObject *dict = *dictptr;
-	if (dict == NULL) {
-	  dict = PyDict_New();
-	  *dictptr = dict;
-	  PyDict_SetItem(dict, SWIG_This(), swig_this);
-	}
+        PyObject *dict = *dictptr;
+        if (dict == NULL) {
+          dict = PyDict_New();
+          *dictptr = dict;
+        }
+        if (dict) {
+          PyDict_SetItem(dict, SWIG_This(), swig_this);
+        } else{
+          Py_DECREF(inst);
+          inst = 0;
+        }
       }
 #else
       if (PyObject_SetAttr(inst, SWIG_This(), swig_this) == -1) {
@@ -1256,7 +1291,11 @@
       dict = PyDict_New();
       *dictptr = dict;
     }
-    return PyDict_SetItem(dict, SWIG_This(), swig_this);
+    if (dict) {
+      return PyDict_SetItem(dict, SWIG_This(), swig_this);
+    } else{
+      return -1;
+    }
   }
 #endif
   return PyObject_SetAttr(inst, SWIG_This(), swig_this);
@@ -1271,7 +1310,7 @@
   } else {
     SwigPyObject *sthis = SWIG_Python_GetSwigThis(obj[0]);
     if (sthis) {
-      SwigPyObject_append((PyObject*) sthis, obj[1]);
+      Py_DECREF(SwigPyObject_append((PyObject*) sthis, obj[1]));
     } else {
       if (SWIG_Python_SetSwigThis(obj[0], obj[1]) != 0)
         return NULL;
@@ -1310,7 +1349,9 @@
     } else {
       newobj = PyObject_New(SwigPyObject, clientdata->pytype);
 #ifdef SWIGPYTHON_BUILTIN
-      newobj->dict = 0;
+      if (newobj) {
+        newobj->dict = 0;
+      }
 #endif
     }
     if (newobj) {
@@ -1349,6 +1390,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 +1425,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 +1445,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)
 {
@@ -1422,8 +1467,10 @@
     descriptor = SWIG_TypeQueryModule(swig_module, swig_module, type);
     if (descriptor) {
       obj = PyCapsule_New((void*) descriptor, NULL, NULL);
-      PyDict_SetItem(cache, key, obj);
-      Py_DECREF(obj);
+      if (obj) {
+        PyDict_SetItem(cache, key, obj);
+        Py_DECREF(obj);
+      }
     }
   }
   Py_DECREF(key);
@@ -1566,7 +1613,7 @@
   }
 
   if (!tp->tp_dict) {
-    if (PyType_Ready(tp) < 0)
+    if (PyType_Ready(tp) != 0)
       goto done;
   }
 
@@ -1581,7 +1628,7 @@
     } else {
       encoded_name = PyUnicode_AsUTF8String(name);
       if (!encoded_name)
-        return -1;
+        goto done;
     }
     PyErr_Format(PyExc_AttributeError, "'%.100s' object has no attribute '%.200s'", tp->tp_name, PyString_AsString(encoded_name));
     Py_DECREF(encoded_name);