aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Lukacs Berki <lberki@google.com>2016-06-24 12:35:08 +0000
committerGravatar Lukacs Berki <lberki@google.com>2016-06-24 12:38:33 +0000
commit83c78b1a8c772b13822386c555c6472d2912f320 (patch)
tree30d92ff6d59d081e4d40cd1152c5037e5769d47d /src
parent19fd76f4376fab4f11e11099aeaf34d36e1d44df (diff)
Make Windows command line quoting work.
Fixes #1445. -- MOS_MIGRATED_REVID=125773835
Diffstat (limited to 'src')
-rw-r--r--src/main/cpp/blaze_util_mingw.cc44
1 files changed, 34 insertions, 10 deletions
diff --git a/src/main/cpp/blaze_util_mingw.cc b/src/main/cpp/blaze_util_mingw.cc
index 287cefb3c6..d4403fba2c 100644
--- a/src/main/cpp/blaze_util_mingw.cc
+++ b/src/main/cpp/blaze_util_mingw.cc
@@ -146,6 +146,10 @@ void ReplaceAll(
// Max command line length is per CreateProcess documentation
// (https://msdn.microsoft.com/en-us/library/ms682425(VS.85).aspx)
+//
+// Quoting rules are described here:
+// https://blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/23/everyone-quotes-command-line-arguments-the-wrong-way/
+
static const int MAX_CMDLINE_LENGTH = 32768;
struct CmdLine {
@@ -169,19 +173,39 @@ static void CreateCommandLine(CmdLine* result, const string& exe,
cmdline.append(" ");
}
- string arg = s;
- // Quote quotes.
- if (s.find("\"") != string::npos) {
- ReplaceAll(&arg, "\"", "\\\"");
- }
+ bool has_space = s.find(" ") != string::npos;
- // Quotize spaces.
- if (arg.find(" ") != string::npos) {
+ if (has_space) {
cmdline.append("\"");
- cmdline.append(arg);
+ }
+
+ std::string::const_iterator it = s.begin();
+ while (it != s.end()) {
+ char ch = *it++;
+ switch (ch) {
+ case '"':
+ // Escape double quotes
+ cmdline.append("\\\"");
+ break;
+
+ case '\\':
+ if (it == s.end()) {
+ // Backslashes at the end of the string are quoted if we add quotes
+ cmdline.append(has_space ? "\\\\" : "\\");
+ } else {
+ // Backslashes everywhere else are quoted if they are followed by a
+ // quote or a backslash
+ cmdline.append(*it == '"' || *it == '\\' ? "\\\\" : "\\");
+ }
+ break;
+
+ default:
+ cmdline.append(1, ch);
+ }
+ }
+
+ if (has_space) {
cmdline.append("\"");
- } else {
- cmdline.append(arg);
}
}