[libvirt] [PATCH python 06/14] override: Replace PyString_AsString with libvirt_charPtrUnwrap

Daniel P. Berrange berrange at redhat.com
Mon Dec 9 15:15:41 UTC 2013


From: "Daniel P. Berrange" <berrange at redhat.com>

Replace calls to PyString_AsString with the helper method
libvirt_charPtrUnwrap. This isolates the code that will
change in Python3.

In making this change, all callers now have responsibility
for free'ing the string.

Signed-off-by: Daniel P. Berrange <berrange at redhat.com>
---
 libvirt-override.c | 106 +++++++++++++++++++++++++++++++----------------------
 typewrappers.c     |  18 +++++++++
 typewrappers.h     |   1 +
 3 files changed, 81 insertions(+), 44 deletions(-)

diff --git a/libvirt-override.c b/libvirt-override.c
index 84a5436..579ea43 100644
--- a/libvirt-override.c
+++ b/libvirt-override.c
@@ -58,18 +58,17 @@ extern void initcygvirtmod(void);
 #define VIR_PY_INT_FAIL (libvirt_intWrap(-1))
 #define VIR_PY_INT_SUCCESS (libvirt_intWrap(0))
 
-/* We don't want to free() returned value. As written in doc:
- * PyString_AsString returns pointer to 'internal buffer of string,
- * not a copy' and 'It must not be deallocated'. */
 static char *py_str(PyObject *obj)
 {
     PyObject *str = PyObject_Str(obj);
+    char *ret;
     if (!str) {
         PyErr_Print();
         PyErr_Clear();
         return NULL;
     };
-    return PyString_AsString(str);
+    libvirt_charPtrUnwrap(str, &ret);
+    return ret;
 }
 
 /* Helper function to convert a virTypedParameter output array into a
@@ -147,9 +146,8 @@ cleanup:
 /* Allocate a new typed parameter array with the same contents and
  * length as info, and using the array params of length nparams as
  * hints on what types to use when creating the new array. The caller
- * must NOT clear the array before freeing it, as it points into info
- * rather than allocated strings.  Return NULL on failure, after
- * raising a python exception.  */
+ * must clear the array before freeing it. Return NULL on failure,
+ * after raising a python exception.  */
 static virTypedParameterPtr ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2)
 setPyVirTypedParameter(PyObject *info,
                        const virTypedParameter *params, int nparams)
@@ -183,7 +181,8 @@ setPyVirTypedParameter(PyObject *info,
     while (PyDict_Next(info, &pos, &key, &value)) {
         char *keystr = NULL;
 
-        if ((keystr = PyString_AsString(key)) == NULL)
+        if (libvirt_charPtrUnwrap(key, &keystr) < 0 ||
+            keystr == NULL)
             goto cleanup;
 
         for (i = 0; i < nparams; i++) {
@@ -194,12 +193,14 @@ setPyVirTypedParameter(PyObject *info,
             PyErr_Format(PyExc_LookupError,
                          "Attribute name \"%s\" could not be recognized",
                          keystr);
+            free(keystr);
             goto cleanup;
         }
 
         strncpy(temp->field, keystr, sizeof(*temp->field) - 1);
         temp->field[sizeof(*temp->field) - 1] = '\0';
         temp->type = params[i].type;
+        free(keystr);
 
         switch (params[i].type) {
         case VIR_TYPED_PARAM_INT:
@@ -237,8 +238,9 @@ setPyVirTypedParameter(PyObject *info,
         }
         case VIR_TYPED_PARAM_STRING:
         {
-            char *string_val = PyString_AsString(value);
-            if (!string_val)
+            char *string_val;
+            if (libvirt_charPtrUnwrap(value, &string_val) < 0 ||
+                !string_val)
                 goto cleanup;
             temp->value.s = string_val;
             break;
@@ -297,6 +299,7 @@ virPyDictToTypedParams(PyObject *dict,
     int n = 0;
     int max = 0;
     int ret = -1;
+    char *keystr = NULL;
 
     *ret_params = NULL;
     *ret_nparams = 0;
@@ -305,10 +308,10 @@ virPyDictToTypedParams(PyObject *dict,
         return -1;
 
     while (PyDict_Next(dict, &pos, &key, &value)) {
-        char *keystr;
         int type = -1;
 
-        if (!(keystr = PyString_AsString(key)))
+        if (libvirt_charPtrUnwrap(key, &keystr) < 0 ||
+            !keystr)
             goto cleanup;
 
         for (i = 0; i < nhints; i++) {
@@ -396,15 +399,20 @@ virPyDictToTypedParams(PyObject *dict,
         }
         case VIR_TYPED_PARAM_STRING:
         {
-            char *val = PyString_AsString(value);
-            if (!val ||
-                virTypedParamsAddString(&params, &n, &max, keystr, val) < 0)
+            char *val;;
+            if (libvirt_charPtrUnwrap(value, &val) < 0 ||
+                !val ||
+                virTypedParamsAddString(&params, &n, &max, keystr, val) < 0) {
+                VIR_FREE(val);
                 goto cleanup;
+            }
+            VIR_FREE(val);
             break;
         }
         case VIR_TYPED_PARAM_LAST:
             break; /* unreachable */
         }
+        VIR_FREE(keystr);
     }
 
     *ret_params = params;
@@ -413,6 +421,7 @@ virPyDictToTypedParams(PyObject *dict,
     ret = 0;
 
 cleanup:
+    VIR_FREE(keystr);
     virTypedParamsFree(params, n);
     return ret;
 }
@@ -957,7 +966,7 @@ libvirt_virDomainSetSchedulerParameters(PyObject *self ATTRIBUTE_UNUSED,
 
 cleanup:
     virTypedParamsFree(params, nparams);
-    VIR_FREE(new_params);
+    virTypedParamsFree(new_params, nparams);
     return ret;
 }
 
@@ -1033,7 +1042,7 @@ libvirt_virDomainSetSchedulerParametersFlags(PyObject *self ATTRIBUTE_UNUSED,
 
 cleanup:
     virTypedParamsFree(params, nparams);
-    VIR_FREE(new_params);
+    virTypedParamsFree(new_params, nparams);
     return ret;
 }
 
@@ -1107,7 +1116,7 @@ libvirt_virDomainSetBlkioParameters(PyObject *self ATTRIBUTE_UNUSED,
 
 cleanup:
     virTypedParamsFree(params, nparams);
-    VIR_FREE(new_params);
+    virTypedParamsFree(new_params, nparams);
     return ret;
 }
 
@@ -1227,7 +1236,7 @@ libvirt_virDomainSetMemoryParameters(PyObject *self ATTRIBUTE_UNUSED,
 
 cleanup:
     virTypedParamsFree(params, nparams);
-    VIR_FREE(new_params);
+    virTypedParamsFree(new_params, nparams);
     return ret;
 }
 
@@ -1347,7 +1356,7 @@ libvirt_virDomainSetNumaParameters(PyObject *self ATTRIBUTE_UNUSED,
 
 cleanup:
     virTypedParamsFree(params, nparams);
-    VIR_FREE(new_params);
+    virTypedParamsFree(new_params, nparams);
     return ret;
 }
 
@@ -1468,7 +1477,7 @@ libvirt_virDomainSetInterfaceParameters(PyObject *self ATTRIBUTE_UNUSED,
 
 cleanup:
     virTypedParamsFree(params, nparams);
-    VIR_FREE(new_params);
+    virTypedParamsFree(new_params, nparams);
     return ret;
 }
 
@@ -2163,9 +2172,9 @@ static int virConnectCredCallbackWrapper(virConnectCredentialPtr cred,
             pycreditem = PyTuple_GetItem(pycred, i);
             pyresult = PyList_GetItem(pycreditem, 4);
             if (pyresult != Py_None)
-                result = PyString_AsString(pyresult);
+                libvirt_charPtrUnwrap(pyresult, &result);
             if (result != NULL) {
-                cred[i].result = strdup(result);
+                cred[i].result = result;
                 cred[i].resultlen = strlen(result);
             } else {
                 cred[i].result = NULL;
@@ -2942,7 +2951,7 @@ libvirt_virDomainGetSecurityLabelList(PyObject *self ATTRIBUTE_UNUSED, PyObject
         PyObject *entry = PyList_New(2);
         PyList_SetItem(entry, 0, libvirt_constcharPtrWrap(&labels[i].label[0]));
         PyList_SetItem(entry, 1, libvirt_boolWrap(labels[i].enforcing));
-	PyList_Append(py_retval, entry);
+        PyList_Append(py_retval, entry);
     }
     free(labels);
     return py_retval;
@@ -4566,10 +4575,11 @@ libvirt_virConnectBaselineCPU(PyObject *self ATTRIBUTE_UNUSED,
     PyObject *list;
     virConnectPtr conn;
     unsigned int flags;
-    const char **xmlcpus = NULL;
+    char **xmlcpus = NULL;
     int ncpus = 0;
     char *base_cpu;
     PyObject *pybase_cpu;
+    size_t i, j;
 
     if (!PyArg_ParseTuple(args, (char *)"OOi:virConnectBaselineCPU",
                           &pyobj_conn, &list, &flags))
@@ -4577,15 +4587,15 @@ libvirt_virConnectBaselineCPU(PyObject *self ATTRIBUTE_UNUSED,
     conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn);
 
     if (PyList_Check(list)) {
-        size_t i;
-
         ncpus = PyList_Size(list);
         if (VIR_ALLOC_N(xmlcpus, ncpus) < 0)
             return VIR_PY_NONE;
 
         for (i = 0; i < ncpus; i++) {
-            xmlcpus[i] = PyString_AsString(PyList_GetItem(list, i));
-            if (xmlcpus[i] == NULL) {
+            if (libvirt_charPtrUnwrap(PyList_GetItem(list, i), &(xmlcpus[i])) < 0 ||
+                xmlcpus[i] == NULL) {
+                for (j = 0 ; j < i ; j++)
+                    VIR_FREE(xmlcpus[j]);
                 VIR_FREE(xmlcpus);
                 return VIR_PY_NONE;
             }
@@ -4593,9 +4603,11 @@ libvirt_virConnectBaselineCPU(PyObject *self ATTRIBUTE_UNUSED,
     }
 
     LIBVIRT_BEGIN_ALLOW_THREADS;
-    base_cpu = virConnectBaselineCPU(conn, xmlcpus, ncpus, flags);
+    base_cpu = virConnectBaselineCPU(conn, (const char **)xmlcpus, ncpus, flags);
     LIBVIRT_END_ALLOW_THREADS;
 
+    for (i = 0 ; i < ncpus ; i++)
+        VIR_FREE(xmlcpus[i]);
     VIR_FREE(xmlcpus);
 
     if (base_cpu == NULL)
@@ -4821,7 +4833,7 @@ libvirt_virDomainSetBlockIoTune(PyObject *self ATTRIBUTE_UNUSED,
 
 cleanup:
     virTypedParamsFree(params, nparams);
-    VIR_FREE(new_params);
+    virTypedParamsFree(new_params, nparams);
     return ret;
 }
 
@@ -5105,18 +5117,18 @@ libvirt_virConnectDomainEventDeregister(ATTRIBUTE_UNUSED PyObject * self,
 /*******************************************
  * Event Impl
  *******************************************/
-static PyObject *addHandleObj     = NULL;
-static char *addHandleName        = NULL;
-static PyObject *updateHandleObj  = NULL;
-static char *updateHandleName     = NULL;
-static PyObject *removeHandleObj  = NULL;
-static char *removeHandleName     = NULL;
-static PyObject *addTimeoutObj    = NULL;
-static char *addTimeoutName       = NULL;
-static PyObject *updateTimeoutObj = NULL;
-static char *updateTimeoutName    = NULL;
-static PyObject *removeTimeoutObj = NULL;
-static char *removeTimeoutName    = NULL;
+static PyObject *addHandleObj;
+static char *addHandleName;
+static PyObject *updateHandleObj;
+static char *updateHandleName;
+static PyObject *removeHandleObj;
+static char *removeHandleName;
+static PyObject *addTimeoutObj;
+static char *addTimeoutName;
+static PyObject *updateTimeoutObj;
+static char *updateTimeoutName;
+static PyObject *removeTimeoutObj;
+static char *removeTimeoutName;
 
 #define NAME(fn) ( fn ## Name ? fn ## Name : # fn )
 
@@ -5381,6 +5393,12 @@ libvirt_virEventRegisterImpl(ATTRIBUTE_UNUSED PyObject * self,
     Py_XDECREF(addTimeoutObj);
     Py_XDECREF(updateTimeoutObj);
     Py_XDECREF(removeTimeoutObj);
+    free(addHandleName);
+    free(updateHandleName);
+    free(removeHandleName);
+    free(addTimeoutName);
+    free(updateTimeoutName);
+    free(removeTimeoutName);
 
     /* Parse and check arguments */
     if (!PyArg_ParseTuple(args, (char *) "OOOOOO:virEventRegisterImpl",
@@ -7084,7 +7102,7 @@ libvirt_virNodeSetMemoryParameters(PyObject *self ATTRIBUTE_UNUSED,
 
 cleanup:
     virTypedParamsFree(params, nparams);
-    VIR_FREE(new_params);
+    virTypedParamsFree(new_params, nparams);
     return ret;
 }
 
diff --git a/typewrappers.c b/typewrappers.c
index 1622986..1e99554 100644
--- a/typewrappers.c
+++ b/typewrappers.c
@@ -317,6 +317,24 @@ libvirt_boolUnwrap(PyObject *obj, bool *val)
     return 0;
 }
 
+int
+libvirt_charPtrUnwrap(PyObject *obj, char **str)
+{
+    const char *ret;
+    *str = NULL;
+    if (!obj) {
+        PyErr_SetString(PyExc_TypeError, "unexpected type");
+        return -1;
+    }
+
+    ret = PyString_AsString(obj);
+    if (ret &&
+        !(*str = strdup(ret)))
+        return -1;
+
+    return 0;
+}
+
 PyObject *
 libvirt_virDomainPtrWrap(virDomainPtr node)
 {
diff --git a/typewrappers.h b/typewrappers.h
index 04e364f..7068426 100644
--- a/typewrappers.h
+++ b/typewrappers.h
@@ -173,6 +173,7 @@ int libvirt_longlongUnwrap(PyObject *obj, long long *val);
 int libvirt_ulonglongUnwrap(PyObject *obj, unsigned long long *val);
 int libvirt_doubleUnwrap(PyObject *obj, double *val);
 int libvirt_boolUnwrap(PyObject *obj, bool *val);
+int libvirt_charPtrUnwrap(PyObject *obj, char **str);
 PyObject * libvirt_virConnectPtrWrap(virConnectPtr node);
 PyObject * libvirt_virDomainPtrWrap(virDomainPtr node);
 PyObject * libvirt_virNetworkPtrWrap(virNetworkPtr node);
-- 
1.8.3.1




More information about the libvir-list mailing list