[libvirt] [PATCHv3] snapshot: fix memory leak on error
Daniel Veillard
veillard at redhat.com
Fri Apr 6 04:56:54 UTC 2012
On Thu, Apr 05, 2012 at 10:24:49PM -0600, Eric Blake wrote:
> Leak introduced in commit 0436d32. If we allocate an actions array,
> but fail early enough to never consume it with the qemu monitor
> transaction call, we leaked memory.
>
> But our semantics of making the transaction command free the caller's
> memory is awkward; avoiding the memory leak requires making every
> intermediate function in the call chain check for error. It is much
> easier to fix things so that the function that allocates also frees,
> while the call chain leaves the caller's data intact. To do that,
> I had to hack our JSON data structure to make it easy to protect a
> portion of an arbitrary JSON tree from being freed.
>
> * src/util/json.h (virJSONType): Name the enum.
> (_virJSONValue): New field.
> * src/util/json.c (virJSONValueFree): Use it to protect a portion
> of an array.
> * src/qemu/qemu_monitor_json.c (qemuMonitorJSONTransaction): Avoid
> freeing caller's data.
> * src/qemu/qemu_driver.c (qemuDomainSnapshotCreateDiskActive):
> Free actions array on failure.
> ---
>
> v3: make the protection orthogonal to the typing.
>
> src/qemu/qemu_driver.c | 1 +
> src/qemu/qemu_monitor_json.c | 11 ++++++-----
> src/util/json.c | 9 ++++++---
> src/util/json.h | 9 +++++----
> 4 files changed, 18 insertions(+), 12 deletions(-)
>
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index dd79973..0456b34 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -10127,6 +10127,7 @@ qemuDomainSnapshotCreateDiskActive(virConnectPtr conn,
> if (actions) {
> if (ret == 0)
> ret = qemuMonitorTransaction(priv->mon, actions);
> + virJSONValueFree(actions);
> if (ret < 0) {
> /* Transaction failed; undo the changes to vm. */
> bool need_unlink = !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_REUSE_EXT);
> diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
> index 7093e1d..8eeb307 100644
> --- a/src/qemu/qemu_monitor_json.c
> +++ b/src/qemu/qemu_monitor_json.c
> @@ -3157,22 +3157,19 @@ cleanup:
> return ret;
> }
>
> -/* Note that this call frees actions regardless of whether the call
> - * succeeds. */
> int
> qemuMonitorJSONTransaction(qemuMonitorPtr mon, virJSONValuePtr actions)
> {
> int ret;
> virJSONValuePtr cmd;
> virJSONValuePtr reply = NULL;
> + bool protect;
>
> cmd = qemuMonitorJSONMakeCommand("transaction",
> "a:actions", actions,
> NULL);
> - if (!cmd) {
> - virJSONValueFree(actions);
> + if (!cmd)
> return -1;
> - }
>
> if ((ret = qemuMonitorJSONCommand(mon, cmd, &reply)) < 0)
> goto cleanup;
> @@ -3180,7 +3177,11 @@ qemuMonitorJSONTransaction(qemuMonitorPtr mon, virJSONValuePtr actions)
> ret = qemuMonitorJSONCheckError(cmd, reply);
>
> cleanup:
> + /* We do NOT want to free actions when recursively freeing cmd. */
> + protect = actions->protect;
> + actions->protect = true;
> virJSONValueFree(cmd);
> + actions->protect = protect;
> virJSONValueFree(reply);
> return ret;
> }
> diff --git a/src/util/json.c b/src/util/json.c
> index a85f580..3258c3f 100644
> --- a/src/util/json.c
> +++ b/src/util/json.c
> @@ -1,7 +1,7 @@
> /*
> * json.c: JSON object parsing/formatting
> *
> - * Copyright (C) 2009-2010 Red Hat, Inc.
> + * Copyright (C) 2009-2010, 2012 Red Hat, Inc.
> * Copyright (C) 2009 Daniel P. Berrange
> *
> * This library is free software; you can redistribute it and/or
> @@ -67,10 +67,10 @@ struct _virJSONParser {
> void virJSONValueFree(virJSONValuePtr value)
> {
> int i;
> - if (!value)
> + if (!value || value->protect)
> return;
>
> - switch (value->type) {
> + switch ((virJSONType) value->type) {
> case VIR_JSON_TYPE_OBJECT:
> for (i = 0 ; i < value->data.object.npairs; i++) {
> VIR_FREE(value->data.object.pairs[i].key);
> @@ -89,6 +89,9 @@ void virJSONValueFree(virJSONValuePtr value)
> case VIR_JSON_TYPE_NUMBER:
> VIR_FREE(value->data.number);
> break;
> + case VIR_JSON_TYPE_BOOLEAN:
> + case VIR_JSON_TYPE_NULL:
> + break;
> }
>
> VIR_FREE(value);
> diff --git a/src/util/json.h b/src/util/json.h
> index 4572654..686a8fb 100644
> --- a/src/util/json.h
> +++ b/src/util/json.h
> @@ -1,8 +1,8 @@
> /*
> * json.h: JSON object parsing/formatting
> *
> + * Copyright (C) 2009, 2012 Red Hat, Inc.
> * Copyright (C) 2009 Daniel P. Berrange
> - * Copyright (C) 2009 Red Hat, Inc.
> *
> * This library is free software; you can redistribute it and/or
> * modify it under the terms of the GNU Lesser General Public
> @@ -27,14 +27,14 @@
> # include "internal.h"
>
>
> -enum {
> +typedef enum {
> VIR_JSON_TYPE_OBJECT,
> VIR_JSON_TYPE_ARRAY,
> VIR_JSON_TYPE_STRING,
> VIR_JSON_TYPE_NUMBER,
> VIR_JSON_TYPE_BOOLEAN,
> VIR_JSON_TYPE_NULL,
> -};
> +} virJSONType;
>
> typedef struct _virJSONValue virJSONValue;
> typedef virJSONValue *virJSONValuePtr;
> @@ -65,7 +65,8 @@ struct _virJSONArray {
> };
>
> struct _virJSONValue {
> - int type;
> + int type; /* enum virJSONType */
> + bool protect; /* prevents deletion when embedded in another object */
>
> union {
> virJSONObject object;
ACK, sounds better to me than piggy-backing on an enum value :-)
Daniel
--
Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/
daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/
http://veillard.com/ | virtualization library http://libvirt.org/
More information about the libvir-list
mailing list