aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar David Leverton <levertond@googlemail.com> 2014-08-28 20:36:49 +0100
committerAvatar David Leverton <levertond@googlemail.com> 2014-08-28 20:36:49 +0100
commit134128bbb7f2907e80987f23e7a605ec30becf77 (patch)
treeca85f3816788ffea20cc4de91de01c07de6ae3aa
parent2d8c07fb1d39165bd762bd191e51213dc7ac6415 (diff)
downloadpaludis-134128bbb7f2907e80987f23e7a605ec30becf77.tar.gz
paludis-134128bbb7f2907e80987f23e7a605ec30becf77.tar.xz
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).
-rw-r--r--paludis/util/config_file.cc5
-rw-r--r--paludis/util/config_file_TEST.cc19
2 files changed, 23 insertions, 1 deletions
diff --git a/paludis/util/config_file.cc b/paludis/util/config_file.cc
index 112c53a..708df81 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 4c0376b..d6c102b 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<Map<std::string, std::string>>());
+ 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;