[libvirt] [libvirt-python PATCH] fix leak in memoryStats with older python

Martin Kletzander mkletzan at redhat.com
Tue May 27 15:33:25 UTC 2014


On Tue, May 27, 2014 at 05:28:32PM +0200, Martin Kletzander wrote:

https://bugzilla.redhat.com/show_bug.cgi?id=1099860

>libvirt_virDomainMemoryStats() function creates a dictionary without
>any checks whether the additions were successful, whether the python
>objects were created and, most importantly, without decrementing the
>reference count on the objects added to the dictionary.  This is
>somehow not an issue with current upstream versions, however with
>python 2.6 this exposes a leak in our bindings.  The following patch
>works on both old and new CPython versions and is already used in
>other parts of the code, so it's also most straightforward.
>
>Signed-off-by: Martin Kletzander <mkletzan at redhat.com>
>---
> libvirt-override.c | 68 +++++++++++++++++++++++++++++++++++-------------------
> 1 file changed, 44 insertions(+), 24 deletions(-)
>
>diff --git a/libvirt-override.c b/libvirt-override.c
>index a7a6213..8fd856b 100644
>--- a/libvirt-override.c
>+++ b/libvirt-override.c
>@@ -734,6 +734,7 @@ libvirt_virDomainMemoryStats(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
>     size_t i;
>     virDomainMemoryStatStruct stats[VIR_DOMAIN_MEMORY_STAT_NR];
>     PyObject *info;
>+    PyObject *key = NULL, *val = NULL;
>
>     if (!PyArg_ParseTuple(args, (char *)"O:virDomainMemoryStats", &pyobj_domain))
>         return NULL;
>@@ -749,31 +750,50 @@ libvirt_virDomainMemoryStats(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
>         return VIR_PY_NONE;
>
>     for (i = 0; i < nr_stats; i++) {
>-        if (stats[i].tag == VIR_DOMAIN_MEMORY_STAT_SWAP_IN)
>-            PyDict_SetItem(info, libvirt_constcharPtrWrap("swap_in"),
>-                           libvirt_ulonglongWrap(stats[i].val));
>-        else if (stats[i].tag == VIR_DOMAIN_MEMORY_STAT_SWAP_OUT)
>-            PyDict_SetItem(info, libvirt_constcharPtrWrap("swap_out"),
>-                           libvirt_ulonglongWrap(stats[i].val));
>-        else if (stats[i].tag == VIR_DOMAIN_MEMORY_STAT_MAJOR_FAULT)
>-            PyDict_SetItem(info, libvirt_constcharPtrWrap("major_fault"),
>-                           libvirt_ulonglongWrap(stats[i].val));
>-        else if (stats[i].tag == VIR_DOMAIN_MEMORY_STAT_MINOR_FAULT)
>-            PyDict_SetItem(info, libvirt_constcharPtrWrap("minor_fault"),
>-                           libvirt_ulonglongWrap(stats[i].val));
>-        else if (stats[i].tag == VIR_DOMAIN_MEMORY_STAT_UNUSED)
>-            PyDict_SetItem(info, libvirt_constcharPtrWrap("unused"),
>-                           libvirt_ulonglongWrap(stats[i].val));
>-        else if (stats[i].tag == VIR_DOMAIN_MEMORY_STAT_AVAILABLE)
>-            PyDict_SetItem(info, libvirt_constcharPtrWrap("available"),
>-                           libvirt_ulonglongWrap(stats[i].val));
>-        else if (stats[i].tag == VIR_DOMAIN_MEMORY_STAT_ACTUAL_BALLOON)
>-            PyDict_SetItem(info, libvirt_constcharPtrWrap("actual"),
>-                           libvirt_ulonglongWrap(stats[i].val));
>-        else if (stats[i].tag == VIR_DOMAIN_MEMORY_STAT_RSS)
>-            PyDict_SetItem(info, libvirt_constcharPtrWrap("rss"),
>-                           libvirt_ulonglongWrap(stats[i].val));
>+        switch (stats[i].tag) {
>+        case VIR_DOMAIN_MEMORY_STAT_SWAP_IN:
>+            key = libvirt_constcharPtrWrap("swap_in");
>+            break;
>+        case VIR_DOMAIN_MEMORY_STAT_SWAP_OUT:
>+            key = libvirt_constcharPtrWrap("swap_out");
>+            break;
>+        case VIR_DOMAIN_MEMORY_STAT_MAJOR_FAULT:
>+            key = libvirt_constcharPtrWrap("major_fault");
>+            break;
>+        case VIR_DOMAIN_MEMORY_STAT_MINOR_FAULT:
>+            key = libvirt_constcharPtrWrap("minor_fault");
>+            break;
>+        case VIR_DOMAIN_MEMORY_STAT_UNUSED:
>+            key = libvirt_constcharPtrWrap("unused");
>+            break;
>+        case VIR_DOMAIN_MEMORY_STAT_AVAILABLE:
>+            key = libvirt_constcharPtrWrap("available");
>+            break;
>+        case VIR_DOMAIN_MEMORY_STAT_ACTUAL_BALLOON:
>+            key = libvirt_constcharPtrWrap("actual");
>+            break;
>+        case VIR_DOMAIN_MEMORY_STAT_RSS:
>+            key = libvirt_constcharPtrWrap("rss");
>+            break;
>+        default:
>+            continue;
>+        }
>+        val = libvirt_ulonglongWrap(stats[i].val);
>+
>+        if (!key || !val || PyDict_SetItem(info, key, val) < 0) {
>+            Py_DECREF(info);
>+            info = NULL;
>+            goto cleanup;
>+        }
>+        Py_DECREF(key);
>+        Py_DECREF(val);
>+        key = NULL;
>+        val = NULL;
>     }
>+
>+ cleanup:
>+    Py_XDECREF(key);
>+    Py_XDECREF(val);
>     return info;
> }
>
>--
>1.9.3
>
>--
>libvir-list mailing list
>libvir-list at redhat.com
>https://www.redhat.com/mailman/listinfo/libvir-list
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20140527/69027533/attachment-0001.sig>


More information about the libvir-list mailing list