From 655369e67f568060b587c1f02c83046ff03c6ed8 Mon Sep 17 00:00:00 2001
From: Piotr Bartosiewicz
Date: Tue, 3 Mar 2015 12:24:50 +0100
Subject: [PATCH] Fix memleaks in GVariant visitor
[Bug/Feature] There were mem leaks in two cases:
- during processing union fields
- when invalid field type exception was thrown
[Cause] N/A
[Solution] N/A
[Verification] Run tests under valgrind
Change-Id: I9ddce15a89b151301549dde0056cf1357c50b47c
---
src/config/from-gvariant-visitor.hpp | 39 ++++++++++++++++++++----------------
1 file changed, 22 insertions(+), 17 deletions(-)
diff --git a/src/config/from-gvariant-visitor.hpp b/src/config/from-gvariant-visitor.hpp
index ba7dc7e..4a0330a 100644
--- a/src/config/from-gvariant-visitor.hpp
+++ b/src/config/from-gvariant-visitor.hpp
@@ -31,6 +31,7 @@
#include
#include
+#include
#include
#include
@@ -60,26 +61,20 @@ public:
template
void visit(const std::string& name, T& value)
{
- GVariant* child = g_variant_iter_next_value(mIter);
- if (child == NULL) {
+ auto child = makeUnique(g_variant_iter_next_value(mIter));
+ if (!child) {
throw config::ConfigException(
"GVariant doesn't match with config. Can't set '" + name + "'");
}
- fromGVariant(child, value);
- g_variant_unref(child);
+ fromGVariant(child.get(), value);
}
private:
GVariantIter* mIter;
- explicit FromGVariantVisitor(GVariant* variant, bool isUnion)
+ static std::unique_ptr makeUnique(GVariant* variant)
{
- if (isUnion) {
- checkType(variant, G_VARIANT_TYPE_VARIANT);
- variant = g_variant_get_variant(variant);
- }
- checkType(variant, G_VARIANT_TYPE_TUPLE);
- mIter = g_variant_iter_new(variant);
+ return std::unique_ptr(variant, g_variant_unref);
}
static void checkType(GVariant* object, const GVariantType* type)
@@ -128,18 +123,28 @@ private:
int length = g_variant_iter_n_children(&iter);
value.resize(static_cast(length));
for (int i = 0; i < length; ++i) {
- GVariant* child = g_variant_iter_next_value(&iter);
- assert(child != NULL);
- fromGVariant(child, value[static_cast(i)]);
- g_variant_unref(child);
+ auto child = makeUnique(g_variant_iter_next_value(&iter));
+ assert(child);
+ fromGVariant(child.get(), value[static_cast(i)]);
}
}
template
- static typename std::enable_if::value>::type
+ static typename std::enable_if::value>::type
+ fromGVariant(GVariant* object, T& value)
+ {
+ checkType(object, G_VARIANT_TYPE_VARIANT);
+ auto inner = makeUnique(g_variant_get_variant(object));
+
+ FromGVariantVisitor visitor(inner.get());
+ value.accept(visitor);
+ }
+
+ template
+ static typename std::enable_if::value && !isUnion::value>::type
fromGVariant(GVariant* object, T& value)
{
- FromGVariantVisitor visitor(object, isUnion::value);
+ FromGVariantVisitor visitor(object);
value.accept(visitor);
}
--
2.7.4