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