Pablo Greco e6a3ae
From 6abc65aaa666bf41070fa772293982cb0d1ae835 Mon Sep 17 00:00:00 2001
Pablo Greco e6a3ae
From: Laszlo Ersek <lersek@redhat.com>
Pablo Greco e6a3ae
Date: Thu, 12 Sep 2019 13:05:00 +0100
Pablo Greco e6a3ae
Subject: [PATCH 03/22] opts: don't silently truncate long option values
Pablo Greco e6a3ae
MIME-Version: 1.0
Pablo Greco e6a3ae
Content-Type: text/plain; charset=UTF-8
Pablo Greco e6a3ae
Content-Transfer-Encoding: 8bit
Pablo Greco e6a3ae
Pablo Greco e6a3ae
RH-Author: Laszlo Ersek <lersek@redhat.com>
Pablo Greco e6a3ae
Message-id: <20190912130503.14094-4-lersek@redhat.com>
Pablo Greco e6a3ae
Patchwork-id: 90436
Pablo Greco e6a3ae
O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 3/6] opts: don't silently truncate long option values
Pablo Greco e6a3ae
Bugzilla: 1749022
Pablo Greco e6a3ae
RH-Acked-by: Stefano Garzarella <sgarzare@redhat.com>
Pablo Greco e6a3ae
RH-Acked-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Pablo Greco e6a3ae
RH-Acked-by: Eduardo Habkost <ehabkost@redhat.com>
Pablo Greco e6a3ae
Pablo Greco e6a3ae
From: Daniel P. Berrangé <berrange@redhat.com>
Pablo Greco e6a3ae
Pablo Greco e6a3ae
The existing QemuOpts parsing code uses a fixed size 1024 byte buffer
Pablo Greco e6a3ae
for storing the option values. If a value exceeded this size it was
Pablo Greco e6a3ae
silently truncated and no error reported to the user. Long option values
Pablo Greco e6a3ae
is not a common scenario, but it is conceivable that they will happen.
Pablo Greco e6a3ae
eg if the user has a very deeply nested filesystem it would be possible
Pablo Greco e6a3ae
to come up with a disk path that was > 1024 bytes. Most of the time if
Pablo Greco e6a3ae
such data was silently truncated, the user would get an error about
Pablo Greco e6a3ae
opening a non-existant disk. If they're unlucky though, QEMU might use a
Pablo Greco e6a3ae
completely different disk image from another VM, which could be
Pablo Greco e6a3ae
considered a security issue. Another example program was in using the
Pablo Greco e6a3ae
-smbios command line arg with very large data blobs. In this case the
Pablo Greco e6a3ae
silent truncation will be providing semantically incorrect data to the
Pablo Greco e6a3ae
guest OS for SMBIOS tables.
Pablo Greco e6a3ae
Pablo Greco e6a3ae
If the operating system didn't limit the user's argv when spawning QEMU,
Pablo Greco e6a3ae
the code should honour whatever length arguments were given without
Pablo Greco e6a3ae
imposing its own length restrictions. This patch thus changes the code
Pablo Greco e6a3ae
to use a heap allocated buffer for storing the values during parsing,
Pablo Greco e6a3ae
lifting the arbitrary length restriction.
Pablo Greco e6a3ae
Pablo Greco e6a3ae
RHEL8 notes:
Pablo Greco e6a3ae
Pablo Greco e6a3ae
- Fix up upstream's obviously garbled UTF8 sequences in Dan's name (Author
Pablo Greco e6a3ae
  meta-datum, Signed-off-by tags).
Pablo Greco e6a3ae
Pablo Greco e6a3ae
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
Pablo Greco e6a3ae
Message-Id: <20180416111743.8473-4-berrange@redhat.com>
Pablo Greco e6a3ae
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Pablo Greco e6a3ae
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
Pablo Greco e6a3ae
(cherry picked from commit 950c4e6c94b15cd0d8b63891dddd7a8dbf458e6a)
Pablo Greco e6a3ae
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Pablo Greco e6a3ae
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
Pablo Greco e6a3ae
---
Pablo Greco e6a3ae
 hw/i386/multiboot.c   |  33 +++++++++------
Pablo Greco e6a3ae
 include/qemu/option.h |   2 +-
Pablo Greco e6a3ae
 util/qemu-option.c    | 111 +++++++++++++++++++++++++++-----------------------
Pablo Greco e6a3ae
 3 files changed, 81 insertions(+), 65 deletions(-)
Pablo Greco e6a3ae
Pablo Greco e6a3ae
diff --git a/hw/i386/multiboot.c b/hw/i386/multiboot.c
Pablo Greco e6a3ae
index 5bc0a2c..7a2953e 100644
Pablo Greco e6a3ae
--- a/hw/i386/multiboot.c
Pablo Greco e6a3ae
+++ b/hw/i386/multiboot.c
Pablo Greco e6a3ae
@@ -291,12 +291,16 @@ int load_multiboot(FWCfgState *fw_cfg,
Pablo Greco e6a3ae
     cmdline_len = strlen(kernel_filename) + 1;
Pablo Greco e6a3ae
     cmdline_len += strlen(kernel_cmdline) + 1;
Pablo Greco e6a3ae
     if (initrd_filename) {
Pablo Greco e6a3ae
-        const char *r = initrd_filename;
Pablo Greco e6a3ae
+        const char *r = get_opt_value(initrd_filename, NULL);
Pablo Greco e6a3ae
         cmdline_len += strlen(r) + 1;
Pablo Greco e6a3ae
         mbs.mb_mods_avail = 1;
Pablo Greco e6a3ae
-        while (*(r = get_opt_value(NULL, 0, r))) {
Pablo Greco e6a3ae
-           mbs.mb_mods_avail++;
Pablo Greco e6a3ae
-           r++;
Pablo Greco e6a3ae
+        while (1) {
Pablo Greco e6a3ae
+            mbs.mb_mods_avail++;
Pablo Greco e6a3ae
+            r = get_opt_value(r, NULL);
Pablo Greco e6a3ae
+            if (!*r) {
Pablo Greco e6a3ae
+                break;
Pablo Greco e6a3ae
+            }
Pablo Greco e6a3ae
+            r++;
Pablo Greco e6a3ae
         }
Pablo Greco e6a3ae
     }
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
@@ -313,7 +317,8 @@ int load_multiboot(FWCfgState *fw_cfg,
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
     if (initrd_filename) {
Pablo Greco e6a3ae
         const char *next_initrd;
Pablo Greco e6a3ae
-        char not_last, tmpbuf[strlen(initrd_filename) + 1];
Pablo Greco e6a3ae
+        char not_last;
Pablo Greco e6a3ae
+        char *one_file = NULL;
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
         mbs.offset_mods = mbs.mb_buf_size;
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
@@ -322,24 +327,26 @@ int load_multiboot(FWCfgState *fw_cfg,
Pablo Greco e6a3ae
             int mb_mod_length;
Pablo Greco e6a3ae
             uint32_t offs = mbs.mb_buf_size;
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
-            next_initrd = get_opt_value(tmpbuf, sizeof(tmpbuf), initrd_filename);
Pablo Greco e6a3ae
+            next_initrd = get_opt_value(initrd_filename, &one_file);
Pablo Greco e6a3ae
             not_last = *next_initrd;
Pablo Greco e6a3ae
             /* if a space comes after the module filename, treat everything
Pablo Greco e6a3ae
                after that as parameters */
Pablo Greco e6a3ae
-            hwaddr c = mb_add_cmdline(&mbs, tmpbuf);
Pablo Greco e6a3ae
-            if ((next_space = strchr(tmpbuf, ' ')))
Pablo Greco e6a3ae
+            hwaddr c = mb_add_cmdline(&mbs, one_file);
Pablo Greco e6a3ae
+            next_space = strchr(one_file, ' ');
Pablo Greco e6a3ae
+            if (next_space) {
Pablo Greco e6a3ae
                 *next_space = '\0';
Pablo Greco e6a3ae
-            mb_debug("multiboot loading module: %s", tmpbuf);
Pablo Greco e6a3ae
-            mb_mod_length = get_image_size(tmpbuf);
Pablo Greco e6a3ae
+            }
Pablo Greco e6a3ae
+            mb_debug("multiboot loading module: %s", one_file);
Pablo Greco e6a3ae
+            mb_mod_length = get_image_size(one_file);
Pablo Greco e6a3ae
             if (mb_mod_length < 0) {
Pablo Greco e6a3ae
-                error_report("Failed to open file '%s'", tmpbuf);
Pablo Greco e6a3ae
+                error_report("Failed to open file '%s'", one_file);
Pablo Greco e6a3ae
                 exit(1);
Pablo Greco e6a3ae
             }
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
             mbs.mb_buf_size = TARGET_PAGE_ALIGN(mb_mod_length + mbs.mb_buf_size);
Pablo Greco e6a3ae
             mbs.mb_buf = g_realloc(mbs.mb_buf, mbs.mb_buf_size);
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
-            load_image(tmpbuf, (unsigned char *)mbs.mb_buf + offs);
Pablo Greco e6a3ae
+            load_image(one_file, (unsigned char *)mbs.mb_buf + offs);
Pablo Greco e6a3ae
             mb_add_mod(&mbs, mbs.mb_buf_phys + offs,
Pablo Greco e6a3ae
                        mbs.mb_buf_phys + offs + mb_mod_length, c);
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
@@ -347,6 +354,8 @@ int load_multiboot(FWCfgState *fw_cfg,
Pablo Greco e6a3ae
                      (char *)mbs.mb_buf + offs,
Pablo Greco e6a3ae
                      (char *)mbs.mb_buf + offs + mb_mod_length, c);
Pablo Greco e6a3ae
             initrd_filename = next_initrd+1;
Pablo Greco e6a3ae
+            g_free(one_file);
Pablo Greco e6a3ae
+            one_file = NULL;
Pablo Greco e6a3ae
         } while (not_last);
Pablo Greco e6a3ae
     }
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
diff --git a/include/qemu/option.h b/include/qemu/option.h
Pablo Greco e6a3ae
index 1cfe5cb..3dfb449 100644
Pablo Greco e6a3ae
--- a/include/qemu/option.h
Pablo Greco e6a3ae
+++ b/include/qemu/option.h
Pablo Greco e6a3ae
@@ -28,7 +28,7 @@
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
 #include "qemu/queue.h"
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
-const char *get_opt_value(char *buf, int buf_size, const char *p);
Pablo Greco e6a3ae
+const char *get_opt_value(const char *p, char **value);
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
 void parse_option_size(const char *name, const char *value,
Pablo Greco e6a3ae
                        uint64_t *ret, Error **errp);
Pablo Greco e6a3ae
diff --git a/util/qemu-option.c b/util/qemu-option.c
Pablo Greco e6a3ae
index b99568f..ba44a08 100644
Pablo Greco e6a3ae
--- a/util/qemu-option.c
Pablo Greco e6a3ae
+++ b/util/qemu-option.c
Pablo Greco e6a3ae
@@ -70,25 +70,37 @@ static const char *get_opt_name(const char *p, char **option, char delim)
Pablo Greco e6a3ae
  * delimiter is fixed to be comma which starts a new option. To specify an
Pablo Greco e6a3ae
  * option value that contains commas, double each comma.
Pablo Greco e6a3ae
  */
Pablo Greco e6a3ae
-const char *get_opt_value(char *buf, int buf_size, const char *p)
Pablo Greco e6a3ae
+const char *get_opt_value(const char *p, char **value)
Pablo Greco e6a3ae
 {
Pablo Greco e6a3ae
-    char *q;
Pablo Greco e6a3ae
+    size_t capacity = 0, length;
Pablo Greco e6a3ae
+    const char *offset;
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
+    *value = NULL;
Pablo Greco e6a3ae
+    while (1) {
Pablo Greco e6a3ae
+        offset = strchr(p, ',');
Pablo Greco e6a3ae
+        if (!offset) {
Pablo Greco e6a3ae
+            offset = p + strlen(p);
Pablo Greco e6a3ae
+        }
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
-    q = buf;
Pablo Greco e6a3ae
-    while (*p != '\0') {
Pablo Greco e6a3ae
-        if (*p == ',') {
Pablo Greco e6a3ae
-            if (*(p + 1) != ',')
Pablo Greco e6a3ae
-                break;
Pablo Greco e6a3ae
-            p++;
Pablo Greco e6a3ae
+        length = offset - p;
Pablo Greco e6a3ae
+        if (*offset != '\0' && *(offset + 1) == ',') {
Pablo Greco e6a3ae
+            length++;
Pablo Greco e6a3ae
+        }
Pablo Greco e6a3ae
+        if (value) {
Pablo Greco e6a3ae
+            *value = g_renew(char, *value, capacity + length + 1);
Pablo Greco e6a3ae
+            strncpy(*value + capacity, p, length);
Pablo Greco e6a3ae
+            (*value)[capacity + length] = '\0';
Pablo Greco e6a3ae
+        }
Pablo Greco e6a3ae
+        capacity += length;
Pablo Greco e6a3ae
+        if (*offset == '\0' ||
Pablo Greco e6a3ae
+            *(offset + 1) != ',') {
Pablo Greco e6a3ae
+            break;
Pablo Greco e6a3ae
         }
Pablo Greco e6a3ae
-        if (q && (q - buf) < buf_size - 1)
Pablo Greco e6a3ae
-            *q++ = *p;
Pablo Greco e6a3ae
-        p++;
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
+        p += (offset - p) + 2;
Pablo Greco e6a3ae
     }
Pablo Greco e6a3ae
-    if (q)
Pablo Greco e6a3ae
-        *q = '\0';
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
-    return p;
Pablo Greco e6a3ae
+    return offset;
Pablo Greco e6a3ae
 }
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
 static void parse_option_bool(const char *name, const char *value, bool *ret,
Pablo Greco e6a3ae
@@ -162,50 +174,43 @@ void parse_option_size(const char *name, const char *value,
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
 bool has_help_option(const char *param)
Pablo Greco e6a3ae
 {
Pablo Greco e6a3ae
-    size_t buflen = strlen(param) + 1;
Pablo Greco e6a3ae
-    char *buf = g_malloc(buflen);
Pablo Greco e6a3ae
     const char *p = param;
Pablo Greco e6a3ae
     bool result = false;
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
-    while (*p) {
Pablo Greco e6a3ae
-        p = get_opt_value(buf, buflen, p);
Pablo Greco e6a3ae
+    while (*p && !result) {
Pablo Greco e6a3ae
+        char *value;
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
+        p = get_opt_value(p, &value);
Pablo Greco e6a3ae
         if (*p) {
Pablo Greco e6a3ae
             p++;
Pablo Greco e6a3ae
         }
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
-        if (is_help_option(buf)) {
Pablo Greco e6a3ae
-            result = true;
Pablo Greco e6a3ae
-            goto out;
Pablo Greco e6a3ae
-        }
Pablo Greco e6a3ae
+        result = is_help_option(value);
Pablo Greco e6a3ae
+        g_free(value);
Pablo Greco e6a3ae
     }
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
-out:
Pablo Greco e6a3ae
-    g_free(buf);
Pablo Greco e6a3ae
     return result;
Pablo Greco e6a3ae
 }
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
-bool is_valid_option_list(const char *param)
Pablo Greco e6a3ae
+bool is_valid_option_list(const char *p)
Pablo Greco e6a3ae
 {
Pablo Greco e6a3ae
-    size_t buflen = strlen(param) + 1;
Pablo Greco e6a3ae
-    char *buf = g_malloc(buflen);
Pablo Greco e6a3ae
-    const char *p = param;
Pablo Greco e6a3ae
-    bool result = true;
Pablo Greco e6a3ae
+    char *value = NULL;
Pablo Greco e6a3ae
+    bool result = false;
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
     while (*p) {
Pablo Greco e6a3ae
-        p = get_opt_value(buf, buflen, p);
Pablo Greco e6a3ae
-        if (*p && !*++p) {
Pablo Greco e6a3ae
-            result = false;
Pablo Greco e6a3ae
+        p = get_opt_value(p, &value);
Pablo Greco e6a3ae
+        if ((*p && !*++p) ||
Pablo Greco e6a3ae
+            (!*value || *value == ',')) {
Pablo Greco e6a3ae
             goto out;
Pablo Greco e6a3ae
         }
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
-        if (!*buf || *buf == ',') {
Pablo Greco e6a3ae
-            result = false;
Pablo Greco e6a3ae
-            goto out;
Pablo Greco e6a3ae
-        }
Pablo Greco e6a3ae
+        g_free(value);
Pablo Greco e6a3ae
+        value = NULL;
Pablo Greco e6a3ae
     }
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
+    result = true;
Pablo Greco e6a3ae
 out:
Pablo Greco e6a3ae
-    g_free(buf);
Pablo Greco e6a3ae
+    g_free(value);
Pablo Greco e6a3ae
     return result;
Pablo Greco e6a3ae
 }
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
@@ -486,7 +491,7 @@ int qemu_opt_unset(QemuOpts *opts, const char *name)
Pablo Greco e6a3ae
     }
Pablo Greco e6a3ae
 }
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
-static void opt_set(QemuOpts *opts, const char *name, const char *value,
Pablo Greco e6a3ae
+static void opt_set(QemuOpts *opts, const char *name, char *value,
Pablo Greco e6a3ae
                     bool prepend, Error **errp)
Pablo Greco e6a3ae
 {
Pablo Greco e6a3ae
     QemuOpt *opt;
Pablo Greco e6a3ae
@@ -495,6 +500,7 @@ static void opt_set(QemuOpts *opts, const char *name, const char *value,
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
     desc = find_desc_by_name(opts->list->desc, name);
Pablo Greco e6a3ae
     if (!desc && !opts_accepts_any(opts)) {
Pablo Greco e6a3ae
+        g_free(value);
Pablo Greco e6a3ae
         error_setg(errp, QERR_INVALID_PARAMETER, name);
Pablo Greco e6a3ae
         return;
Pablo Greco e6a3ae
     }
Pablo Greco e6a3ae
@@ -508,8 +514,7 @@ static void opt_set(QemuOpts *opts, const char *name, const char *value,
Pablo Greco e6a3ae
         QTAILQ_INSERT_TAIL(&opts->head, opt, next);
Pablo Greco e6a3ae
     }
Pablo Greco e6a3ae
     opt->desc = desc;
Pablo Greco e6a3ae
-    opt->str = g_strdup(value);
Pablo Greco e6a3ae
-    assert(opt->str);
Pablo Greco e6a3ae
+    opt->str = value;
Pablo Greco e6a3ae
     qemu_opt_parse(opt, &local_err);
Pablo Greco e6a3ae
     if (local_err) {
Pablo Greco e6a3ae
         error_propagate(errp, local_err);
Pablo Greco e6a3ae
@@ -520,7 +525,7 @@ static void opt_set(QemuOpts *opts, const char *name, const char *value,
Pablo Greco e6a3ae
 void qemu_opt_set(QemuOpts *opts, const char *name, const char *value,
Pablo Greco e6a3ae
                   Error **errp)
Pablo Greco e6a3ae
 {
Pablo Greco e6a3ae
-    opt_set(opts, name, value, false, errp);
Pablo Greco e6a3ae
+    opt_set(opts, name, g_strdup(value), false, errp);
Pablo Greco e6a3ae
 }
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
 void qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val,
Pablo Greco e6a3ae
@@ -754,7 +759,7 @@ static void opts_do_parse(QemuOpts *opts, const char *params,
Pablo Greco e6a3ae
                           const char *firstname, bool prepend, Error **errp)
Pablo Greco e6a3ae
 {
Pablo Greco e6a3ae
     char *option = NULL;
Pablo Greco e6a3ae
-    char value[1024];
Pablo Greco e6a3ae
+    char *value = NULL;
Pablo Greco e6a3ae
     const char *p,*pe,*pc;
Pablo Greco e6a3ae
     Error *local_err = NULL;
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
@@ -766,15 +771,15 @@ static void opts_do_parse(QemuOpts *opts, const char *params,
Pablo Greco e6a3ae
             if (p == params && firstname) {
Pablo Greco e6a3ae
                 /* implicitly named first option */
Pablo Greco e6a3ae
                 option = g_strdup(firstname);
Pablo Greco e6a3ae
-                p = get_opt_value(value, sizeof(value), p);
Pablo Greco e6a3ae
+                p = get_opt_value(p, &value);
Pablo Greco e6a3ae
             } else {
Pablo Greco e6a3ae
                 /* option without value, probably a flag */
Pablo Greco e6a3ae
                 p = get_opt_name(p, &option, ',');
Pablo Greco e6a3ae
                 if (strncmp(option, "no", 2) == 0) {
Pablo Greco e6a3ae
                     memmove(option, option+2, strlen(option+2)+1);
Pablo Greco e6a3ae
-                    pstrcpy(value, sizeof(value), "off");
Pablo Greco e6a3ae
+                    value = g_strdup("off");
Pablo Greco e6a3ae
                 } else {
Pablo Greco e6a3ae
-                    pstrcpy(value, sizeof(value), "on");
Pablo Greco e6a3ae
+                    value = g_strdup("on");
Pablo Greco e6a3ae
                 }
Pablo Greco e6a3ae
             }
Pablo Greco e6a3ae
         } else {
Pablo Greco e6a3ae
@@ -782,11 +787,12 @@ static void opts_do_parse(QemuOpts *opts, const char *params,
Pablo Greco e6a3ae
             p = get_opt_name(p, &option, '=');
Pablo Greco e6a3ae
             assert(*p == '=');
Pablo Greco e6a3ae
             p++;
Pablo Greco e6a3ae
-            p = get_opt_value(value, sizeof(value), p);
Pablo Greco e6a3ae
+            p = get_opt_value(p, &value);
Pablo Greco e6a3ae
         }
Pablo Greco e6a3ae
         if (strcmp(option, "id") != 0) {
Pablo Greco e6a3ae
             /* store and parse */
Pablo Greco e6a3ae
             opt_set(opts, option, value, prepend, &local_err);
Pablo Greco e6a3ae
+            value = NULL;
Pablo Greco e6a3ae
             if (local_err) {
Pablo Greco e6a3ae
                 error_propagate(errp, local_err);
Pablo Greco e6a3ae
                 goto cleanup;
Pablo Greco e6a3ae
@@ -796,11 +802,13 @@ static void opts_do_parse(QemuOpts *opts, const char *params,
Pablo Greco e6a3ae
             break;
Pablo Greco e6a3ae
         }
Pablo Greco e6a3ae
         g_free(option);
Pablo Greco e6a3ae
-        option = NULL;
Pablo Greco e6a3ae
+        g_free(value);
Pablo Greco e6a3ae
+        option = value = NULL;
Pablo Greco e6a3ae
     }
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
  cleanup:
Pablo Greco e6a3ae
     g_free(option);
Pablo Greco e6a3ae
+    g_free(value);
Pablo Greco e6a3ae
 }
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
 /**
Pablo Greco e6a3ae
@@ -819,7 +827,7 @@ static QemuOpts *opts_parse(QemuOptsList *list, const char *params,
Pablo Greco e6a3ae
                             bool permit_abbrev, bool defaults, Error **errp)
Pablo Greco e6a3ae
 {
Pablo Greco e6a3ae
     const char *firstname;
Pablo Greco e6a3ae
-    char value[1024], *id = NULL;
Pablo Greco e6a3ae
+    char *id = NULL;
Pablo Greco e6a3ae
     const char *p;
Pablo Greco e6a3ae
     QemuOpts *opts;
Pablo Greco e6a3ae
     Error *local_err = NULL;
Pablo Greco e6a3ae
@@ -828,11 +836,9 @@ static QemuOpts *opts_parse(QemuOptsList *list, const char *params,
Pablo Greco e6a3ae
     firstname = permit_abbrev ? list->implied_opt_name : NULL;
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
     if (strncmp(params, "id=", 3) == 0) {
Pablo Greco e6a3ae
-        get_opt_value(value, sizeof(value), params+3);
Pablo Greco e6a3ae
-        id = value;
Pablo Greco e6a3ae
+        get_opt_value(params + 3, &id);
Pablo Greco e6a3ae
     } else if ((p = strstr(params, ",id=")) != NULL) {
Pablo Greco e6a3ae
-        get_opt_value(value, sizeof(value), p+4);
Pablo Greco e6a3ae
-        id = value;
Pablo Greco e6a3ae
+        get_opt_value(p + 4, &id);
Pablo Greco e6a3ae
     }
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
     /*
Pablo Greco e6a3ae
@@ -844,6 +850,7 @@ static QemuOpts *opts_parse(QemuOptsList *list, const char *params,
Pablo Greco e6a3ae
      */
Pablo Greco e6a3ae
     assert(!defaults || list->merge_lists);
Pablo Greco e6a3ae
     opts = qemu_opts_create(list, id, !defaults, &local_err);
Pablo Greco e6a3ae
+    g_free(id);
Pablo Greco e6a3ae
     if (opts == NULL) {
Pablo Greco e6a3ae
         error_propagate(errp, local_err);
Pablo Greco e6a3ae
         return NULL;
Pablo Greco e6a3ae
-- 
Pablo Greco e6a3ae
1.8.3.1
Pablo Greco e6a3ae