From a34d060773bc7d1ed713f163057221a6877a4349 Mon Sep 17 00:00:00 2001 From: tony Date: Fri, 1 Jul 2022 15:12:48 +0100 Subject: [PATCH 1/2] Fix for grpc.tools #17995 & protobuf #7474 Use CreateProcessW so that non-ascii paths are handled correctly --- src/google/protobuf/compiler/subprocess.cc | 26 +++++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/src/google/protobuf/compiler/subprocess.cc b/src/google/protobuf/compiler/subprocess.cc index 764f9aba3886..a50cb5694ba5 100644 --- a/src/google/protobuf/compiler/subprocess.cc +++ b/src/google/protobuf/compiler/subprocess.cc @@ -47,6 +47,7 @@ #include #include #include +#include namespace google { namespace protobuf { @@ -113,7 +114,7 @@ void Subprocess::Start(const std::string& program, SearchMode search_mode) { } // Setup STARTUPINFO to redirect handles. - STARTUPINFOA startup_info; + STARTUPINFOW startup_info; ZeroMemory(&startup_info, sizeof(startup_info)); startup_info.cb = sizeof(startup_info); startup_info.dwFlags = STARTF_USESTDHANDLES; @@ -125,17 +126,30 @@ void Subprocess::Start(const std::string& program, SearchMode search_mode) { GOOGLE_LOG(FATAL) << "GetStdHandle: " << Win32ErrorMessage(GetLastError()); } + // get wide string version of program as the path may contain non-ascii characters + std::wstring wprogram; + if (!io::win32::strings::utf8_to_wcs(program.c_str(), &wprogram)) { + GOOGLE_LOG(FATAL) << "utf8_to_wcs: " << Win32ErrorMessage(GetLastError()); + } + // Invoking cmd.exe allows for '.bat' files from the path as well as '.exe'. + std::string command_line = "cmd.exe /c \"" + program + "\""; + + // get wide string version of command line as the path may contain non-ascii characters + std::wstring wcommand_line; + if (!io::win32::strings::utf8_to_wcs(command_line.c_str(), &wcommand_line)) { + GOOGLE_LOG(FATAL) << "utf8_to_wcs: " << Win32ErrorMessage(GetLastError()); + } + // Using a malloc'ed string because CreateProcess() can mutate its second // parameter. - char* command_line = - portable_strdup(("cmd.exe /c \"" + program + "\"").c_str()); + wchar_t *wcommand_line_copy = _wcsdup(wcommand_line.c_str()); // Create the process. PROCESS_INFORMATION process_info; - if (CreateProcessA((search_mode == SEARCH_PATH) ? nullptr : program.c_str(), - (search_mode == SEARCH_PATH) ? command_line : nullptr, + if (CreateProcessW((search_mode == SEARCH_PATH) ? NULL : wprogram.c_str(), + (search_mode == SEARCH_PATH) ? wcommand_line_copy : NULL, nullptr, // process security attributes nullptr, // thread security attributes TRUE, // inherit handles? @@ -155,7 +169,7 @@ void Subprocess::Start(const std::string& program, SearchMode search_mode) { CloseHandleOrDie(stdin_pipe_read); CloseHandleOrDie(stdout_pipe_write); - free(command_line); + free(wcommand_line_copy); } bool Subprocess::Communicate(const Message& input, Message* output, From efa2b29058bd1553e2ad9f95b0abdd46853f6ab7 Mon Sep 17 00:00:00 2001 From: tony Date: Mon, 4 Jul 2022 14:58:44 +0100 Subject: [PATCH 2/2] Use nullptr instead of NULL --- src/google/protobuf/compiler/subprocess.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/google/protobuf/compiler/subprocess.cc b/src/google/protobuf/compiler/subprocess.cc index a50cb5694ba5..6f547db79550 100644 --- a/src/google/protobuf/compiler/subprocess.cc +++ b/src/google/protobuf/compiler/subprocess.cc @@ -148,7 +148,7 @@ void Subprocess::Start(const std::string& program, SearchMode search_mode) { // Create the process. PROCESS_INFORMATION process_info; - if (CreateProcessW((search_mode == SEARCH_PATH) ? NULL : wprogram.c_str(), + if (CreateProcessW((search_mode == SEARCH_PATH) ? nullptr : wprogram.c_str(), (search_mode == SEARCH_PATH) ? wcommand_line_copy : NULL, nullptr, // process security attributes nullptr, // thread security attributes