[fix] Avoid std::regex initialization during dlopen (#406)

This commit is contained in:
Maximilian Knespel 2023-05-30 23:26:34 +02:00 committed by GitHub
parent beda973ec6
commit a526762eb8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -55,8 +55,8 @@ THE SOFTWARE.
#define CXXOPTS_LINKONCE_CONST __declspec(selectany) extern #define CXXOPTS_LINKONCE_CONST __declspec(selectany) extern
#define CXXOPTS_LINKONCE __declspec(selectany) extern #define CXXOPTS_LINKONCE __declspec(selectany) extern
#else #else
#define CXXOPTS_LINKONCE_CONST #define CXXOPTS_LINKONCE_CONST
#define CXXOPTS_LINKONCE #define CXXOPTS_LINKONCE
#endif #endif
#ifndef CXXOPTS_NO_REGEX #ifndef CXXOPTS_NO_REGEX
@ -753,29 +753,31 @@ inline ArguDesc ParseArgument(const char *arg, bool &matched)
namespace { namespace {
CXXOPTS_LINKONCE CXXOPTS_LINKONCE
std::basic_regex<char> integer_pattern const char* const integer_pattern =
("(-)?(0x)?([0-9a-zA-Z]+)|((0x)?0)"); "(-)?(0x)?([0-9a-zA-Z]+)|((0x)?0)";
CXXOPTS_LINKONCE CXXOPTS_LINKONCE
std::basic_regex<char> truthy_pattern const char* const truthy_pattern =
("(t|T)(rue)?|1"); "(t|T)(rue)?|1";
CXXOPTS_LINKONCE CXXOPTS_LINKONCE
std::basic_regex<char> falsy_pattern const char* const falsy_pattern =
("(f|F)(alse)?|0"); "(f|F)(alse)?|0";
CXXOPTS_LINKONCE CXXOPTS_LINKONCE
std::basic_regex<char> option_matcher const char* const option_pattern =
("--([[:alnum:]][-_[:alnum:]\\.]+)(=(.*))?|-([[:alnum:]].*)"); "--([[:alnum:]][-_[:alnum:]\\.]+)(=(.*))?|-([[:alnum:]].*)";
CXXOPTS_LINKONCE CXXOPTS_LINKONCE
std::basic_regex<char> option_specifier const char* const option_specifier_pattern =
("([[:alnum:]][-_[:alnum:]\\.]*)(,[ ]*[[:alnum:]][-_[:alnum:]]*)*"); "([[:alnum:]][-_[:alnum:]\\.]*)(,[ ]*[[:alnum:]][-_[:alnum:]]*)*";
CXXOPTS_LINKONCE CXXOPTS_LINKONCE
std::basic_regex<char> option_specifier_separator(", *"); const char* const option_specifier_separator_pattern = ", *";
} // namespace } // namespace
inline IntegerDesc SplitInteger(const std::string &text) inline IntegerDesc SplitInteger(const std::string &text)
{ {
static const std::basic_regex<char> integer_matcher(integer_pattern);
std::smatch match; std::smatch match;
std::regex_match(text, match, integer_pattern); std::regex_match(text, match, integer_matcher);
if (match.length() == 0) if (match.length() == 0)
{ {
@ -799,15 +801,17 @@ inline IntegerDesc SplitInteger(const std::string &text)
inline bool IsTrueText(const std::string &text) inline bool IsTrueText(const std::string &text)
{ {
static const std::basic_regex<char> truthy_matcher(truthy_pattern);
std::smatch result; std::smatch result;
std::regex_match(text, result, truthy_pattern); std::regex_match(text, result, truthy_matcher);
return !result.empty(); return !result.empty();
} }
inline bool IsFalseText(const std::string &text) inline bool IsFalseText(const std::string &text)
{ {
static const std::basic_regex<char> falsy_matcher(falsy_pattern);
std::smatch result; std::smatch result;
std::regex_match(text, result, falsy_pattern); std::regex_match(text, result, falsy_matcher);
return !result.empty(); return !result.empty();
} }
@ -816,22 +820,25 @@ inline bool IsFalseText(const std::string &text)
// (without considering which or how many are single-character) // (without considering which or how many are single-character)
inline OptionNames split_option_names(const std::string &text) inline OptionNames split_option_names(const std::string &text)
{ {
if (!std::regex_match(text.c_str(), option_specifier)) static const std::basic_regex<char> option_specifier_matcher(option_specifier_pattern);
if (!std::regex_match(text.c_str(), option_specifier_matcher))
{ {
throw_or_mimic<exceptions::invalid_option_format>(text); throw_or_mimic<exceptions::invalid_option_format>(text);
} }
OptionNames split_names; OptionNames split_names;
static const std::basic_regex<char> option_specifier_separator_matcher(option_specifier_separator_pattern);
constexpr int use_non_matches { -1 }; constexpr int use_non_matches { -1 };
auto token_iterator = std::sregex_token_iterator( auto token_iterator = std::sregex_token_iterator(
text.begin(), text.end(), option_specifier_separator, use_non_matches); text.begin(), text.end(), option_specifier_separator_matcher, use_non_matches);
std::copy(token_iterator, std::sregex_token_iterator(), std::back_inserter(split_names)); std::copy(token_iterator, std::sregex_token_iterator(), std::back_inserter(split_names));
return split_names; return split_names;
} }
inline ArguDesc ParseArgument(const char *arg, bool &matched) inline ArguDesc ParseArgument(const char *arg, bool &matched)
{ {
static const std::basic_regex<char> option_matcher(option_pattern);
std::match_results<const char*> result; std::match_results<const char*> result;
std::regex_match(arg, result, option_matcher); std::regex_match(arg, result, option_matcher);
matched = !result.empty(); matched = !result.empty();
@ -1546,7 +1553,7 @@ class ParseResult
Iterator(const Iterator&) = default; Iterator(const Iterator&) = default;
// GCC complains about m_iter not being initialised in the member // GCC complains about m_iter not being initialised in the member
// initializer list // initializer list
CXXOPTS_DIAGNOSTIC_PUSH CXXOPTS_DIAGNOSTIC_PUSH
CXXOPTS_IGNORE_WARNING("-Weffc++") CXXOPTS_IGNORE_WARNING("-Weffc++")
Iterator(const ParseResult *pr, bool end=false) Iterator(const ParseResult *pr, bool end=false)