From fa210c4b50b5d0df8351c0710936dc6d38ec32de Mon Sep 17 00:00:00 2001 From: Harald Nielsen Date: Mon, 25 Sep 2023 12:44:40 +0200 Subject: [PATCH] Handle argument file with none ascii chars --- build_defs/cpp_opts.bzl | 1 + .../compiler/command_line_interface.cc | 13 +++++++----- .../compiler/command_line_interface.h | 6 +++--- src/google/protobuf/compiler/main.cc | 21 +++++++++++++++++-- 4 files changed, 31 insertions(+), 10 deletions(-) diff --git a/build_defs/cpp_opts.bzl b/build_defs/cpp_opts.bzl index 5a32371dacf7f..1bdd6e55e767c 100644 --- a/build_defs/cpp_opts.bzl +++ b/build_defs/cpp_opts.bzl @@ -35,6 +35,7 @@ LINK_OPTS = select({ "//build_defs:config_msvc": [ # Suppress linker warnings about files with no symbols defined. "-ignore:4221", + "Shell32.lib", ], "@platforms//os:macos": [ "-lpthread", diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc index 71dcc46544f71..a8a9e47d6c758 100644 --- a/src/google/protobuf/compiler/command_line_interface.cc +++ b/src/google/protobuf/compiler/command_line_interface.cc @@ -1171,7 +1171,7 @@ FieldOptions::OptionTargetType GetTargetType(const MethodDescriptor*) { } } // namespace -int CommandLineInterface::Run(int argc, const char* const argv[]) { +int CommandLineInterface::Run(int argc, const wchar_t* const argv[]) { Clear(); switch (ParseArguments(argc, argv)) { @@ -1771,7 +1771,7 @@ bool CommandLineInterface::MakeInputsBeProtoPathRelative( bool CommandLineInterface::ExpandArgumentFile( - const std::string& file, std::vector* arguments) { + const std::wstring& file, std::vector* arguments) { // The argument file is searched in the working directory only. We don't // use the proto import path here. std::ifstream file_stream(file.c_str()); @@ -1779,6 +1779,7 @@ bool CommandLineInterface::ExpandArgumentFile( return false; } std::string argument; + // We don't support any kind of shell expansion right now. while (std::getline(file_stream, argument)) { arguments->push_back(argument); @@ -1787,8 +1788,8 @@ bool CommandLineInterface::ExpandArgumentFile( } CommandLineInterface::ParseArgumentStatus CommandLineInterface::ParseArguments( - int argc, const char* const argv[]) { - // executable_name_ = argv[0]; + int argc, const wchar_t* const argv[]) { + executable_name_ = argv[0]; std::vector arguments; for (int i = 1; i < argc; ++i) { @@ -1800,7 +1801,9 @@ CommandLineInterface::ParseArgumentStatus CommandLineInterface::ParseArguments( } continue; } - arguments.push_back(argv[i]); + // We handle arguments as normal char to not ripple wchar_t through the codebase + std::wstring tempWstring(argv[i]); + arguments.push_back(std::string(tempWstring.begin(), tempWstring.end())); } // if no arguments are given, show help diff --git a/src/google/protobuf/compiler/command_line_interface.h b/src/google/protobuf/compiler/command_line_interface.h index b0bf26e2b32a1..f8a4ee8989982 100644 --- a/src/google/protobuf/compiler/command_line_interface.h +++ b/src/google/protobuf/compiler/command_line_interface.h @@ -179,7 +179,7 @@ class PROTOC_EXPORT CommandLineInterface { // // It may not be safe to call Run() in a multi-threaded environment because // it calls strerror(). I'm not sure why you'd want to do this anyway. - int Run(int argc, const char* const argv[]); + int Run(int argc, const wchar_t* const argv[]); // DEPRECATED. Calling this method has no effect. Protocol compiler now // always try to find the .proto file relative to the current directory @@ -231,11 +231,11 @@ class PROTOC_EXPORT CommandLineInterface { }; // Parse all command-line arguments. - ParseArgumentStatus ParseArguments(int argc, const char* const argv[]); + ParseArgumentStatus ParseArguments(int argc, const wchar_t* const argv[]); // Read an argument file and append the file's content to the list of // arguments. Return false if the file cannot be read. - bool ExpandArgumentFile(const std::string& file, + bool ExpandArgumentFile(const std::wstring& file, std::vector* arguments); // Parses a command-line argument into a name/value pair. Returns diff --git a/src/google/protobuf/compiler/main.cc b/src/google/protobuf/compiler/main.cc index 0ade6ace805ca..4d9b2a97ff8d5 100644 --- a/src/google/protobuf/compiler/main.cc +++ b/src/google/protobuf/compiler/main.cc @@ -20,12 +20,13 @@ // Must be included last. #include "google/protobuf/port_def.inc" +#include namespace google { namespace protobuf { namespace compiler { -int ProtobufMain(int argc, char* argv[]) { +int ProtobufMain(int argc, wchar_t* argv[]) { absl::InitializeLog(); CommandLineInterface cli; @@ -101,6 +102,22 @@ int ProtobufMain(int argc, char* argv[]) { } // namespace protobuf } // namespace google + int main(int argc, char* argv[]) { - return google::protobuf::compiler::ProtobufMain(argc, argv); + + wchar_t** wargv; + + #if defined(_MSC_VER) + int wargCount; + wargv = CommandLineToArgvW(GetCommandLineW(), &wargCount); + #else + // convert char** to wchar_t** + wargv = new wchar_t*[argc]; + for (int i = 0; i < argc; ++i) { + wargv[i] = new wchar_t[strlen(argv[i]) + 1]; + mbstowcs(wargv[i], argv[i], strlen(argv[i]) + 1); + } + #endif + + return google::protobuf::compiler::ProtobufMain(argc, wargv); }