On 03/10/2014 01:31 AM, Chunyan Liu wrote:
> Add two temp convert functions between QEMUOptionParameter to QemuOpts, so 
> that
> next patch can use it. It will simplify next patch for easier review.
> 
> Signed-off-by: Chunyan Liu <cy...@suse.com>
> ---
>  include/qemu/option.h |   2 +
>  util/qemu-option.c    | 105 
> ++++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 107 insertions(+)
> 

> +
> +/* convert QEMUOptionParameter to QemuOpts */
> +QemuOptsList *params_to_opts(QEMUOptionParameter *list)
> +{
> +    QemuOptsList *opts = NULL;
> +    size_t num_opts, i = 0;
> +
> +    if (!list) {
> +        return NULL;
> +    }
> +
> +    num_opts = count_option_parameters(list);
> +    opts = g_malloc0(sizeof(QemuOptsList) +
> +                     (num_opts + 1) * sizeof(QemuOptDesc));
> +    QTAILQ_INIT(&opts->head);
> +    opts->desc[i].name = NULL;

Dead assignment to NULL, thanks to the g_malloc0 above.

> +
> +    while (list && list->name) {
> +        opts->desc[i].name = g_strdup(list->name);
> +        opts->desc[i].help = g_strdup(list->help);
> +        switch (list->type) {
> +        case OPT_FLAG:
> +            opts->desc[i].type = QEMU_OPT_BOOL;
> +            opts->desc[i].def_value_str = list->value.n ? "on" : "off";

Ouch.  The pointer used here points to constant memory...

> +            break;
> +
> +        case OPT_NUMBER:
> +            opts->desc[i].type = QEMU_OPT_NUMBER;
> +            if (list->value.n) {
> +                opts->desc[i].def_value_str =
> +                    g_strdup_printf("%" PRIu64, list->value.n);

...while the pointer used here points to heap memory.  Yet I see nothing
in the struct that you use to track whether to free the string or not,
which means this is more likely a memory leak, but also a potential for
a crash during an errant call to g_free().  You absolutely must manage
the memory correctly, if you are going to conditionally heap-allocate
def_value_str.

For the sake of conversions between the two types, may I suggest an idea:
in 'struct QemuOpt', add a char[24] buffer (that's large enough to hold
the maximum stringized uint value).  Then, instead of malloc'ing memory
with g_strdup_printf, you instead format integers in place.  You've
already malloc'd the size for the QemuOpt, and now the string
representation also fits within that space without needing a secondary
malloc.

Whether or not you end up keeping the stringizing buffer permanently
part of QemuOpt, or delete it after you delete QEMUOptionParameter,
remains to be seen at the end of the series.

> +        case OPT_STRING:
> +            opts->desc[i].type = QEMU_OPT_STRING;
> +            opts->desc[i].def_value_str = g_strdup(list->value.s);

Here, just declare that your temporary QemuOptsList result from the
function has a shorter lifetime than the input QemuOptionParameter, and
set the def_value_str pointer to the original list->value.s instead of
duplicating it.  Then, you are back to the situation where freeing the
temporary QemuOptsList doesn't leak and doesn't risk double frees.


> +QEMUOptionParameter *opts_to_params(QemuOpts *opts)
> +{
> +    QEMUOptionParameter *dest = NULL;
> +    QemuOptDesc *desc;
> +    size_t num_opts, i = 0;
> +    const char *tmp;
> +
> +    if (!opts || !opts->list || !opts->list->desc) {
> +        return NULL;
> +    }
> +
> +    num_opts = count_opts_list(opts->list);
> +    dest = g_malloc0((num_opts + 1) * sizeof(QEMUOptionParameter));
> +    dest[i].name = NULL;
> +
> +    desc = opts->list->desc;
> +    while (desc && desc->name) {
> +        dest[i].name = g_strdup(desc->name);
> +        dest[i].help = g_strdup(desc->help);

I didn't research QEMUOptionParameter close enough to know if you will
be causing any memory leaks on the reverse conversion - but since the
end goal of the series is to delete QEMUOptionParameter, this method
will eventually disappear, so I guess I could live with leaks here
(although it would be nice to document it in the commit message, if you
do indeed leak).

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to