diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index feb372e155..5a4b3c7f42 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -1543,67 +1543,78 @@ static int remoteDeserializeTypedParameters(remote_typed_param *ret_params_val, u_int ret_params_len, int limit, - virTypedParameterPtr params, + virTypedParameterPtr *params, int *nparams) { int i = 0; int rv = -1; + bool userAllocated = *params != NULL; - /* Check the length of the returned list carefully. */ - if (ret_params_len > limit || ret_params_len > *nparams) { - virReportError(VIR_ERR_RPC, "%s", - _("returned number of parameters exceeds limit")); - goto cleanup; + if (userAllocated) { + /* Check the length of the returned list carefully. */ + if (ret_params_len > limit || ret_params_len > *nparams) { + virReportError(VIR_ERR_RPC, "%s", + _("returned number of parameters exceeds limit")); + goto cleanup; + } + } else { + if (VIR_ALLOC_N(*params, ret_params_len) < 0) { + virReportOOMError(); + goto cleanup; + } } - *nparams = ret_params_len; /* Deserialise the result. */ for (i = 0; i < ret_params_len; ++i) { - if (virStrcpyStatic(params[i].field, - ret_params_val[i].field) == NULL) { + virTypedParameterPtr param = *params + i; + remote_typed_param *ret_param = ret_params_val + i; + + if (virStrcpyStatic(param->field, + ret_param->field) == NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Parameter %s too big for destination"), - ret_params_val[i].field); + ret_param->field); goto cleanup; } - params[i].type = ret_params_val[i].value.type; - switch (params[i].type) { + + param->type = ret_param->value.type; + switch (param->type) { case VIR_TYPED_PARAM_INT: - params[i].value.i = - ret_params_val[i].value.remote_typed_param_value_u.i; + param->value.i = + ret_param->value.remote_typed_param_value_u.i; break; case VIR_TYPED_PARAM_UINT: - params[i].value.ui = - ret_params_val[i].value.remote_typed_param_value_u.ui; + param->value.ui = + ret_param->value.remote_typed_param_value_u.ui; break; case VIR_TYPED_PARAM_LLONG: - params[i].value.l = - ret_params_val[i].value.remote_typed_param_value_u.l; + param->value.l = + ret_param->value.remote_typed_param_value_u.l; break; case VIR_TYPED_PARAM_ULLONG: - params[i].value.ul = - ret_params_val[i].value.remote_typed_param_value_u.ul; + param->value.ul = + ret_param->value.remote_typed_param_value_u.ul; break; case VIR_TYPED_PARAM_DOUBLE: - params[i].value.d = - ret_params_val[i].value.remote_typed_param_value_u.d; + param->value.d = + ret_param->value.remote_typed_param_value_u.d; break; case VIR_TYPED_PARAM_BOOLEAN: - params[i].value.b = - ret_params_val[i].value.remote_typed_param_value_u.b; + param->value.b = + ret_param->value.remote_typed_param_value_u.b; break; case VIR_TYPED_PARAM_STRING: - params[i].value.s = - strdup(ret_params_val[i].value.remote_typed_param_value_u.s); - if (params[i].value.s == NULL) { + param->value.s = + strdup(ret_param->value.remote_typed_param_value_u.s); + if (!param->value.s) { virReportOOMError(); goto cleanup; } break; default: virReportError(VIR_ERR_RPC, _("unknown parameter type: %d"), - params[i].type); + param->type); goto cleanup; } } @@ -1611,8 +1622,14 @@ remoteDeserializeTypedParameters(remote_typed_param *ret_params_val, rv = 0; cleanup: - if (rv < 0) - virTypedParamsClear(params, i); + if (rv < 0) { + if (userAllocated) { + virTypedParamsClear(*params, i); + } else { + virTypedParamsFree(*params, i); + *params = NULL; + } + } return rv; } @@ -1698,7 +1715,7 @@ remoteDomainBlockStatsFlags(virDomainPtr domain, if (remoteDeserializeTypedParameters(ret.params.params_val, ret.params.params_len, REMOTE_DOMAIN_MEMORY_PARAMETERS_MAX, - params, + ¶ms, nparams) < 0) goto cleanup; @@ -1746,7 +1763,7 @@ remoteDomainGetMemoryParameters(virDomainPtr domain, if (remoteDeserializeTypedParameters(ret.params.params_val, ret.params.params_len, REMOTE_DOMAIN_MEMORY_PARAMETERS_MAX, - params, + ¶ms, nparams) < 0) goto cleanup; @@ -1794,7 +1811,7 @@ remoteDomainGetNumaParameters(virDomainPtr domain, if (remoteDeserializeTypedParameters(ret.params.params_val, ret.params.params_len, REMOTE_DOMAIN_NUMA_PARAMETERS_MAX, - params, + ¶ms, nparams) < 0) goto cleanup; @@ -1842,7 +1859,7 @@ remoteDomainGetBlkioParameters(virDomainPtr domain, if (remoteDeserializeTypedParameters(ret.params.params_val, ret.params.params_len, REMOTE_DOMAIN_BLKIO_PARAMETERS_MAX, - params, + ¶ms, nparams) < 0) goto cleanup; @@ -2658,7 +2675,7 @@ static int remoteDomainGetBlockIoTune(virDomainPtr domain, if (remoteDeserializeTypedParameters(ret.params.params_val, ret.params.params_len, REMOTE_DOMAIN_MEMORY_PARAMETERS_MAX, - params, + ¶ms, nparams) < 0) goto cleanup; @@ -2742,12 +2759,12 @@ static int remoteDomainGetCPUStats(virDomainPtr domain, ncpus = ret.params.params_len / ret.nparams; for (cpu = 0; cpu < ncpus; cpu++) { int tmp = nparams; + virTypedParameterPtr cpu_params = ¶ms[cpu * nparams]; remote_typed_param *stride = &ret.params.params_val[cpu * ret.nparams]; if (remoteDeserializeTypedParameters(stride, ret.nparams, REMOTE_NODE_CPU_STATS_MAX, - ¶ms[cpu * nparams], - &tmp) < 0) + &cpu_params, &tmp) < 0) goto cleanup; } @@ -5648,7 +5665,7 @@ remoteDomainGetInterfaceParameters(virDomainPtr domain, if (remoteDeserializeTypedParameters(ret.params.params_val, ret.params.params_len, REMOTE_DOMAIN_INTERFACE_PARAMETERS_MAX, - params, + ¶ms, nparams) < 0) goto cleanup; @@ -5822,7 +5839,7 @@ remoteNodeGetMemoryParameters(virConnectPtr conn, if (remoteDeserializeTypedParameters(ret.params.params_val, ret.params.params_len, REMOTE_NODE_MEMORY_PARAMETERS_MAX, - params, + ¶ms, nparams) < 0) goto cleanup; diff --git a/src/rpc/gendispatch.pl b/src/rpc/gendispatch.pl index 1da28a471e..ef387e0299 100755 --- a/src/rpc/gendispatch.pl +++ b/src/rpc/gendispatch.pl @@ -1343,7 +1343,7 @@ elsif ($opt_k) { push(@ret_list2, "if (remoteDeserializeTypedParameters(ret.$1.$1_val,\n" . " ret.$1.$1_len,\n" . " $2,\n" . - " $1,\n" . + " &$1,\n" . " n$1) < 0)\n" . " goto cleanup;\n"); $single_ret_cleanup = 1;