]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
fix: Fix parsing of MSVC response files (#1071)
authorjacobly0 <jacobly0@users.noreply.github.com>
Wed, 11 May 2022 18:45:40 +0000 (14:45 -0400)
committerGitHub <noreply@github.com>
Wed, 11 May 2022 18:45:40 +0000 (20:45 +0200)
src/Args.cpp
src/Args.hpp
src/argprocessing.cpp
unittest/test_Args.cpp

index 572911ecea26c28a65a6afce60720cd01776b7f8..6b4ec2183bbce889f6235168f4054b3c662b8510 100644 (file)
@@ -50,7 +50,7 @@ Args::from_string(const std::string& command)
 }
 
 optional<Args>
-Args::from_atfile(const std::string& filename, bool ignore_backslash)
+Args::from_atfile(const std::string& filename, AtFileFormat format)
 {
   std::string argtext;
   try {
@@ -72,17 +72,28 @@ Args::from_atfile(const std::string& filename, bool ignore_backslash)
   while (true) {
     switch (*pos) {
     case '\\':
-      if (ignore_backslash) {
-        break;
-      }
       pos++;
-      if (*pos == '\0') {
-        continue;
+      switch (format) {
+      case AtFileFormat::QuoteAny_EscapeAny:
+        if (*pos == '\0') {
+          continue;
+        }
+        break;
+      case AtFileFormat::QuoteDouble_EscapeQuoteEscape:
+        if (*pos != '"' && *pos != '\\') {
+          pos--;
+        }
+        break;
       }
       break;
 
-    case '"':
     case '\'':
+      if (format == AtFileFormat::QuoteDouble_EscapeQuoteEscape) {
+        break;
+      }
+      // Fall through.
+
+    case '"':
       if (quoting != '\0') {
         if (quoting == *pos) {
           quoting = '\0';
index 1a07ddc7169d4bc47941928e606488300e3a0aa0..75aa331fe253e9ab592384ba54086e20087891a7 100644 (file)
@@ -36,8 +36,14 @@ public:
 
   static Args from_argv(int argc, const char* const* argv);
   static Args from_string(const std::string& command);
-  static nonstd::optional<Args> from_atfile(const std::string& filename,
-                                            bool ignore_backslash = false);
+
+  enum class AtFileFormat {
+    QuoteAny_EscapeAny, // '\'' and '"' quote, '\\' escapes any character
+    QuoteDouble_EscapeQuoteEscape, // '"' quotes, '\\' escapes only '"' and '\\'
+  };
+  static nonstd::optional<Args>
+  from_atfile(const std::string& filename,
+              AtFileFormat format = AtFileFormat::QuoteAny_EscapeAny);
 
   Args& operator=(const Args& other) = default;
   Args& operator=(Args&& other) noexcept;
index a0888b2b191f224343b120a0eec7172d8cb14144..679ee101ec2f2829ed7b11afc541062ababb7015 100644 (file)
@@ -307,7 +307,10 @@ process_arg(const Context& ctx,
       ++argpath;
     }
     auto file_args =
-      Args::from_atfile(argpath, ctx.config.is_compiler_group_msvc());
+      Args::from_atfile(argpath,
+                        config.is_compiler_group_msvc()
+                          ? Args::AtFileFormat::QuoteDouble_EscapeQuoteEscape
+                          : Args::AtFileFormat::QuoteAny_EscapeAny);
     if (!file_args) {
       LOG("Couldn't read arg file {}", argpath);
       return Statistic::bad_compiler_arguments;
index 391b71bd86f13426779e3961f38347ffb3f71de6..ee9f80831f63f93f3bcd9fc7001fd10b83ba6978 100644 (file)
@@ -136,6 +136,25 @@ TEST_CASE("Args::from_atfile")
     CHECK(args[5] == "si'x\" th");
     CHECK(args[6] == "seve\nth");
   }
+
+  SUBCASE("Only escape double quote and backslash in alternate format")
+  {
+    Util::write_file("at_file", "\"\\\"\\a\\ \\\\\\ \\b\\\"\"\\");
+    args = *Args::from_atfile(
+      "at_file", Args::AtFileFormat::QuoteDouble_EscapeQuoteEscape);
+    CHECK(args.size() == 1);
+    CHECK(args[0] == "\"\\a\\ \\\\ \\b\"\\");
+  }
+
+  SUBCASE("Ignore single quote in alternate format")
+  {
+    Util::write_file("at_file", "'a b'");
+    args = *Args::from_atfile(
+      "at_file", Args::AtFileFormat::QuoteDouble_EscapeQuoteEscape);
+    CHECK(args.size() == 2);
+    CHECK(args[0] == "'a");
+    CHECK(args[1] == "b'");
+  }
 }
 
 TEST_CASE("Args copy assignment operator")