From 6273d1136af913aaf4badc4545ccf942557c747b Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Wed, 20 Nov 2013 13:09:20 +0100 Subject: qdict: Fix memory leak in qdict_do_flatten() Reported-by: Laszlo Ersek Signed-off-by: Kevin Wolf Signed-off-by: Stefan Hajnoczi --- qobject/qdict.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'qobject') diff --git a/qobject/qdict.c b/qobject/qdict.c index 0f3e0a6c81..60d6cd5a0e 100644 --- a/qobject/qdict.c +++ b/qobject/qdict.c @@ -481,7 +481,7 @@ static void qdict_do_flatten(QDict *qdict, QDict *target, const char *prefix) { QObject *value; const QDictEntry *entry, *next; - const char *new_key; + char *new_key; bool delete; entry = qdict_first(qdict); @@ -506,6 +506,8 @@ static void qdict_do_flatten(QDict *qdict, QDict *target, const char *prefix) delete = true; } + g_free(new_key); + if (delete) { qdict_del(qdict, entry->key); -- cgit v1.2.1 From 4d5977eaecd3675c1176274a50f74ebc40dd13ec Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Wed, 20 Nov 2013 13:09:21 +0100 Subject: qdict: Optimise qdict_do_flatten() Nested QDicts used to be both entered recursively in order to move their entries to the target QDict and also be moved themselves to the target QDict like all other objects. This is harmless because for the top level, qdict_do_flatten() will encounter the (now empty) QDict for a second time and then delete it, but at the same time it's obviously unnecessary overhead. Just delete nested QDicts directly after moving all of their entries. Reported-by: Laszlo Ersek Signed-off-by: Kevin Wolf Signed-off-by: Stefan Hajnoczi --- qobject/qdict.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'qobject') diff --git a/qobject/qdict.c b/qobject/qdict.c index 60d6cd5a0e..17e14f08b1 100644 --- a/qobject/qdict.c +++ b/qobject/qdict.c @@ -494,16 +494,20 @@ static void qdict_do_flatten(QDict *qdict, QDict *target, const char *prefix) delete = false; if (prefix) { - qobject_incref(value); new_key = g_strdup_printf("%s.%s", prefix, entry->key); - qdict_put_obj(target, new_key, value); - delete = true; } if (qobject_type(value) == QTYPE_QDICT) { + /* Entries of QDicts are processed recursively, the QDict object + * itself disappears. */ qdict_do_flatten(qobject_to_qdict(value), target, new_key ? new_key : entry->key); delete = true; + } else if (prefix) { + /* All other objects are moved to the target unchanged. */ + qobject_incref(value); + qdict_put_obj(target, new_key, value); + delete = true; } g_free(new_key); -- cgit v1.2.1