From 1a638e35b20bb5d1f04090d4bd1db1287df48b9b Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Wed, 30 Sep 2015 10:54:34 +0200 Subject: [PATCH] Fix incorrectly escaped arguments for CreateProcess fixes #10245 --- doc/20-library-reference.md | 1 + lib/base/process.cpp | 2 +- lib/base/scriptutils.cpp | 1 + lib/base/string.hpp | 5 +++++ lib/base/utility.cpp | 34 ++++++++++++++++++++++++++++++++++ lib/base/utility.hpp | 1 + 6 files changed, 43 insertions(+), 1 deletion(-) diff --git a/doc/20-library-reference.md b/doc/20-library-reference.md index 22e695040..b452b4a78 100644 --- a/doc/20-library-reference.md +++ b/doc/20-library-reference.md @@ -21,6 +21,7 @@ get_time() | Returns the current UNIX timestamp. parse_performance_data(pd) | Parses a performance data string and returns an array describing the values. dirname(path) | Returns the directory portion of the specified path. basename(path) | Returns the filename portion of the specified path. +escape\_create\_process\_arg(text)| (Windows only) Escapes a string for use as an argument for CreateProcess(). exit(integer) | Terminates the application. ## Object Accessor Functions diff --git a/lib/base/process.cpp b/lib/base/process.cpp index d192044a8..4f34f9359 100644 --- a/lib/base/process.cpp +++ b/lib/base/process.cpp @@ -133,7 +133,7 @@ Process::Arguments Process::PrepareCommand(const Value& command) if (args != "") args += " "; - args += Utility::EscapeShellArg(argument); + args += Utility::EscapeCreateProcessArg(argument); #else /* _WIN32 */ args.push_back(argument); #endif /* _WIN32 */ diff --git a/lib/base/scriptutils.cpp b/lib/base/scriptutils.cpp index abfffce40..cd2e11651 100644 --- a/lib/base/scriptutils.cpp +++ b/lib/base/scriptutils.cpp @@ -58,6 +58,7 @@ REGISTER_SCRIPTFUNCTION(get_time, &Utility::GetTime); REGISTER_SCRIPTFUNCTION(basename, &Utility::BaseName); REGISTER_SCRIPTFUNCTION(dirname, &Utility::DirName); REGISTER_SCRIPTFUNCTION(msi_get_component_path, &ScriptUtils::MsiGetComponentPathShim); +REGISTER_SCRIPTFUNCTION(escape_create_process_arg, &Utility::EscapeCreateProcessArg); String ScriptUtils::CastString(const Value& value) { diff --git a/lib/base/string.hpp b/lib/base/string.hpp index ad019dc28..74c93f188 100644 --- a/lib/base/string.hpp +++ b/lib/base/string.hpp @@ -204,6 +204,11 @@ public: void Trim(void); + inline void Append(int count, char ch) + { + m_Data.append(count, ch); + } + inline bool Contains(const String& str) const { return (m_Data.find(str) != std::string::npos); diff --git a/lib/base/utility.cpp b/lib/base/utility.cpp index 478b40555..6708a1e6c 100644 --- a/lib/base/utility.cpp +++ b/lib/base/utility.cpp @@ -1016,6 +1016,40 @@ String Utility::EscapeShellArg(const String& s) return result; } +#ifdef _WIN32 +String Utility::EscapeCreateProcessArg(const String& arg) +{ + if (arg.FindFirstOf(" \t\n\v\"") == String::NPos) + return arg; + + String result = "\""; + + for (String::ConstIterator it = arg.Begin(); ; it++) { + int numBackslashes = 0; + + while (it != arg.End() && *it == '\\') { + it++; + numBackslashes++; + } + + if (it == arg.End()) { + result.Append(numBackslashes * 2, '\\'); + break; + } else if (*it == '"') { + result.Append(numBackslashes * 2, '\\'); + result.Append(1, *it); + } else { + result.Append(numBackslashes, '\\'); + result.Append(1, *it); + } + } + + result += "\""; + + return result; +} +#endif /* _WIN32 */ + #ifdef _WIN32 static void WindowsSetThreadName(const char *name) { diff --git a/lib/base/utility.hpp b/lib/base/utility.hpp index c1702193e..0cce4c127 100644 --- a/lib/base/utility.hpp +++ b/lib/base/utility.hpp @@ -108,6 +108,7 @@ public: static String EscapeShellCmd(const String& s); static String EscapeShellArg(const String& s); + static String EscapeCreateProcessArg(const String& arg); static String EscapeString(const String& s, const String& chars); static String UnescapeString(const String& s); -- 2.40.0