diff --git a/include/CLI/impl/App_inl.hpp b/include/CLI/impl/App_inl.hpp index db2dc3df6..ed66dba68 100644 --- a/include/CLI/impl/App_inl.hpp +++ b/include/CLI/impl/App_inl.hpp @@ -1493,7 +1493,7 @@ CLI11_INLINE bool App::_parse_single_config(const ConfigItem &item, std::size_t op->add_result(res); return true; } - if(static_cast(item.inputs.size()) > op->get_items_expected_max()) { + if(static_cast(item.inputs.size()) > op->get_items_expected_max() && op->get_multi_option_policy()!=MultiOptionPolicy::TakeAll) { if(op->get_items_expected_max() > 1) { throw ArgumentMismatch::AtMost(item.fullname(), op->get_items_expected_max(), item.inputs.size()); } diff --git a/include/CLI/impl/Config_inl.hpp b/include/CLI/impl/Config_inl.hpp index 9ce056c45..9adcb95b5 100644 --- a/include/CLI/impl/Config_inl.hpp +++ b/include/CLI/impl/Config_inl.hpp @@ -33,10 +33,6 @@ namespace detail { // check if a given character is printable // the cast is necessary to avoid undefined behaviour if (isprint((unsigned char)c) == 0) { - escaped_string.push_back(c); - } - else - { std::stringstream stream; // if the character is not printable // we'll convert it to a hex string using a stringstream @@ -44,14 +40,28 @@ namespace detail { stream << std::hex << (unsigned int)(unsigned char)(c); std::string code = stream.str(); escaped_string += std::string("\\x")+(code.size()<2?"0":"")+code; + + } + else + { + escaped_string.push_back(c); } } -} - + if (escaped_string != string_to_escape) + { + escaped_string.insert(0,"B(\""); + escaped_string.push_back(')'); + escaped_string.push_back('"'); + } + return escaped_string; + } + CLI11_INLINE bool is_printable(const std::string& test_string) + { + return std::all_of(test_string.begin(), test_string.end(), [](char x) {return (isprint(static_cast(x)) != 0 || x == '\n'); }); +} CLI11_INLINE std::string convert_arg_for_ini(const std::string &arg, char stringQuote, char characterQuote) { - static const std::string elchars=std::string("\n")+'\0'; if(arg.empty()) { return std::string(2, stringQuote); } @@ -69,6 +79,10 @@ CLI11_INLINE std::string convert_arg_for_ini(const std::string &arg, char string } // just quote a single non numeric character if(arg.size() == 1) { + if (isprint(static_cast(arg.front())) == 0) + { + return escape_string(arg); + } return std::string(1, characterQuote) + arg + characterQuote; } // handle hex, binary or octal arguments @@ -89,7 +103,11 @@ CLI11_INLINE std::string convert_arg_for_ini(const std::string &arg, char string } } } - if(arg.find_first_of(elchars) != std::string::npos) { + if (!is_printable(arg)) + { + return escape_string(arg); + } + if (arg.find_first_of("\n") != std::string::npos) { return std::string(tquote) + arg + tquote; } if(arg.find_first_of(stringQuote) == std::string::npos) { diff --git a/tests/FuzzFailTest.cpp b/tests/FuzzFailTest.cpp index e1024adae..a4bf57ed9 100644 --- a/tests/FuzzFailTest.cpp +++ b/tests/FuzzFailTest.cpp @@ -63,7 +63,7 @@ TEST_CASE("app_file_gen_fail") { CLI::FuzzApp fuzzdata; auto app = fuzzdata.generateApp(); - int index = GENERATE(range(8, 9)); + int index = GENERATE(range(1, 9)); std::string optionString, flagString; auto parseData = loadFailureFile("fuzz_app_file_fail", index); if(parseData.size() > 25) {