From: jacobly0 Date: Wed, 11 May 2022 18:45:40 +0000 (-0400) Subject: fix: Fix parsing of MSVC response files (#1071) X-Git-Tag: v4.6.1~14 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1892e4d3e8ece73a922ac8fe883b4391227d2700;p=thirdparty%2Fccache.git fix: Fix parsing of MSVC response files (#1071) --- diff --git a/src/Args.cpp b/src/Args.cpp index 572911ece..6b4ec2183 100644 --- a/src/Args.cpp +++ b/src/Args.cpp @@ -50,7 +50,7 @@ Args::from_string(const std::string& command) } optional -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'; diff --git a/src/Args.hpp b/src/Args.hpp index 1a07ddc71..75aa331fe 100644 --- a/src/Args.hpp +++ b/src/Args.hpp @@ -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 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 + from_atfile(const std::string& filename, + AtFileFormat format = AtFileFormat::QuoteAny_EscapeAny); Args& operator=(const Args& other) = default; Args& operator=(Args&& other) noexcept; diff --git a/src/argprocessing.cpp b/src/argprocessing.cpp index a0888b2b1..679ee101e 100644 --- a/src/argprocessing.cpp +++ b/src/argprocessing.cpp @@ -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; diff --git a/unittest/test_Args.cpp b/unittest/test_Args.cpp index 391b71bd8..ee9f80831 100644 --- a/unittest/test_Args.cpp +++ b/unittest/test_Args.cpp @@ -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")