From 134128bbb7f2907e80987f23e7a605ec30becf77 Mon Sep 17 00:00:00 2001 From: David Leverton Date: Thu, 28 Aug 2014 20:36:49 +0100 Subject: Don't inappropriately rely on evaluation order If the key wasn't already present in the map and there were non-trival default and transformation functions, and the compiler decided to evaluate the LHS of the assignment before the RHS, the [] would create the map entry with an empty string value, which would then be returned by get() and passed to the transformation function instead of using the default. Found by compiling with clang (where it broke the PortageEnvironment tests). --- paludis/util/config_file.cc | 5 ++++- paludis/util/config_file_TEST.cc | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/paludis/util/config_file.cc b/paludis/util/config_file.cc index 112c53a34..708df8186 100644 --- a/paludis/util/config_file.cc +++ b/paludis/util/config_file.cc @@ -810,7 +810,10 @@ KeyValueConfigFile::KeyValueConfigFile( want = false; if (want) - _imp->values[key] = transformation_function()(*this, key, get(key), value); + { + std::string new_value(transformation_function()(*this, key, get(key), value)); + _imp->values[key] = new_value; + } } _imp->active_key_prefix = ""; diff --git a/paludis/util/config_file_TEST.cc b/paludis/util/config_file_TEST.cc index 4c0376b8e..d6c102bc6 100644 --- a/paludis/util/config_file_TEST.cc +++ b/paludis/util/config_file_TEST.cc @@ -56,6 +56,11 @@ namespace { return f.get(s); } + + std::string concatenate(const KeyValueConfigFile &, const std::string &, const std::string & prev, const std::string & value) + { + return prev + value; + } } TEST(LineConfigFile, Works) @@ -238,6 +243,20 @@ TEST(KeyValueConfigFile, Defaults) EXPECT_EQ("cow", ff.get("y")); } +TEST(KeyValueConfigFile, DefaultsAndTransformations) +{ + auto predef(std::make_shared>()); + predef->insert("magic", "xyzzy"); + + std::stringstream d_s; + d_s << "magic=plugh" << std::endl; + KeyValueConfigFile ff(d_s, { }, + std::bind(&predefined, predef, std::placeholders::_1, std::placeholders::_2), + &concatenate); + + EXPECT_EQ("xyzzyplugh", ff.get("magic")); +} + TEST(KeyValueConfigFile, Source) { std::stringstream d_s; -- cgit v1.2.3