about summary refs log tree commit diff
path: root/src/libutil/util.cc
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2014-03-28T15·59+0100
committerEelco Dolstra <eelco.dolstra@logicblox.com>2014-03-28T15·59+0100
commit49009573bc2eacd823d57433daf1f59dfe415065 (patch)
tree7a8a15d1bc549e674f40cffdf0613de7af512b93 /src/libutil/util.cc
parent24cb65efc3c34e24fc653779a4d42cf4f31c6737 (diff)
Don't interpret strings as format strings
Ludo reported this error:

  unexpected Nix daemon error: boost::too_few_args: format-string refered to more arguments than were passed

coming from this line:

  printMsg(lvlError, run.program + ": " + string(err, 0, p));

The problem here is that the string ends up implicitly converted to a
Boost format() object, so % characters are treated specially.  I
always assumed (wrongly) that strings are converted to a format object
that outputs the string as-is.

Since this assumption appears in several places that may be hard to
grep for, I've added some C++ type hackery to ensures that the right
thing happens.  So you don't have to worry about % in statements like

  printMsg(lvlError, "foo: " + s);

or

  throw Error("foo: " + s);
Diffstat (limited to 'src/libutil/util.cc')
-rw-r--r--src/libutil/util.cc26
1 files changed, 13 insertions, 13 deletions
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index b264fc5f3d..15c462ce4e 100644
--- a/src/libutil/util.cc
+++ b/src/libutil/util.cc
@@ -25,22 +25,22 @@ extern char * * environ;
 namespace nix {
 
 
-BaseError::BaseError(const format & f, unsigned int status)
+BaseError::BaseError(const FormatOrString & fs, unsigned int status)
     : status(status)
 {
-    err = f.str();
+    err = fs.s;
 }
 
 
-BaseError & BaseError::addPrefix(const format & f)
+BaseError & BaseError::addPrefix(const FormatOrString & fs)
 {
-    prefix_ = f.str() + prefix_;
+    prefix_ = fs.s + prefix_;
     return *this;
 }
 
 
-SysError::SysError(const format & f)
-    : Error(format("%1%: %2%") % f.str() % strerror(errno))
+SysError::SysError(const FormatOrString & fs)
+    : Error(format("%1%: %2%") % fs.s % strerror(errno))
     , errNo(errno)
 {
 }
@@ -417,14 +417,14 @@ static string escVerbosity(Verbosity level)
 }
 
 
-void Nest::open(Verbosity level, const format & f)
+void Nest::open(Verbosity level, const FormatOrString & fs)
 {
     if (level <= verbosity) {
         if (logType == ltEscapes)
             std::cerr << "\033[" << escVerbosity(level) << "p"
-                      << f.str() << "\n";
+                      << fs.s << "\n";
         else
-            printMsg_(level, f);
+            printMsg_(level, fs);
         nest = true;
         nestingLevel++;
     }
@@ -442,7 +442,7 @@ void Nest::close()
 }
 
 
-void printMsg_(Verbosity level, const format & f)
+void printMsg_(Verbosity level, const FormatOrString & fs)
 {
     checkInterrupt();
     if (level > verbosity) return;
@@ -452,15 +452,15 @@ void printMsg_(Verbosity level, const format & f)
             prefix += "|   ";
     else if (logType == ltEscapes && level != lvlInfo)
         prefix = "\033[" + escVerbosity(level) + "s";
-    string s = (format("%1%%2%\n") % prefix % f.str()).str();
+    string s = (format("%1%%2%\n") % prefix % fs.s).str();
     writeToStderr(s);
 }
 
 
-void warnOnce(bool & haveWarned, const format & f)
+void warnOnce(bool & haveWarned, const FormatOrString & fs)
 {
     if (!haveWarned) {
-        printMsg(lvlError, format("warning: %1%") % f.str());
+        printMsg(lvlError, format("warning: %1%") % fs.s);
         haveWarned = true;
     }
 }