[libvirt] [PATCH python 06/14] override: Replace PyString_AsString with libvirt_charPtrUnwrap
Doug Goldstein
cardoe at gentoo.org
Mon Dec 9 16:33:25 UTC 2013
On Mon, Dec 9, 2013 at 9:15 AM, Daniel P. Berrange <berrange at redhat.com> wrote:
> 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);
Here you use free() but....
> 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(¶ms, &n, &max, keystr, val) < 0)
> + char *val;;
> + if (libvirt_charPtrUnwrap(value, &val) < 0 ||
> + !val ||
> + virTypedParamsAddString(¶ms, &n, &max, keystr, val) < 0) {
> + VIR_FREE(val);
Here you use VIR_FREE(). We should probably be consistent.
> 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;
Not sure the advantage of this change.
>
> #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);
More free() vs VIR_FREE().
>
> /* 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
>
> --
> libvir-list mailing list
> libvir-list at redhat.com
> https://www.redhat.com/mailman/listinfo/libvir-list
Some minor nits but overall looks ok. I'll double check it for any
leaks with more context after I review the rest of the series.
--
Doug Goldstein
More information about the libvir-list
mailing list