diff --git a/src/logging.cc b/src/logging.cc index e58427679..404afc55f 100644 --- a/src/logging.cc +++ b/src/logging.cc @@ -2206,27 +2206,14 @@ static string ShellEscape(const string& src) { } return result; } -#endif - -// Trim whitespace from the start of the provided string. -static inline void ltrim(std::string &s) { - s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](char ch) { - return std::isspace(ch) == 0; - })); -} - -// Trim whitespace from the end of the provided string. -static inline void rtrim(std::string &s) { - s.erase(std::find_if(s.rbegin(), s.rend(), [](char ch) { - return std::isspace(ch) == 0; - }).base(), s.end()); -} // Trim whitespace from both ends of the provided string. static inline void trim(std::string &s) { - rtrim(s); - ltrim(s); + const auto toRemove = [](char ch) { return std::isspace(ch) == 0; }; + s.erase(s.begin(), std::find_if(s.begin(), s.end(), toRemove)); + s.erase(std::find_if(s.rbegin(), s.rend(), toRemove).base(), s.end()); } +#endif // use_logging controls whether the logging functions LOG/VLOG are used // to log errors. It should be set to false when the caller holds the @@ -2234,23 +2221,10 @@ static inline void trim(std::string &s) { static bool SendEmailInternal(const char*dest, const char *subject, const char*body, bool use_logging) { #ifndef GLOG_OS_EMSCRIPTEN - // We validate the provided email addresses using the same regular expression - // that HTML5 uses[1], except that we require the address to start with an - // alpha-numeric character. This is because we don't want to allow email - // addresses that start with a special character, such as a pipe or dash, - // which could be misunderstood as a command-line flag by certain versions - // of `mail` that are vulnerable to command injection.[2] - // [1] https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address - // [2] e.g. https://nvd.nist.gov/vuln/detail/CVE-2004-2771 - const std::regex pattern("^[a-zA-Z0-9]" - "[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]*@[a-zA-Z0-9]" - "(?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9]" - "(?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$"); - if (dest && *dest) { // Split the comma-separated list of email addresses, validate each one and // build a sanitized new comma-separated string without whitespace. - std::stringstream ss(dest); + std::istringstream ss(dest); std::ostringstream sanitized_dests; std::string s; while (std::getline(ss, s, ',')) { @@ -2258,7 +2232,20 @@ static bool SendEmailInternal(const char*dest, const char *subject, if (s.empty()) { continue; } - if (!std::regex_match(s, pattern)) { + // We validate the provided email addresses using the same regular + // expression that HTML5 uses[1], except that we require the address to + // start with an alpha-numeric character. This is because we don't want to + // allow email addresses that start with a special character, such as a + // pipe or dash, which could be misunderstood as a command-line flag by + // certain versions of `mail` that are vulnerable to command injection.[2] + // [1] https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address + // [2] e.g. https://nvd.nist.gov/vuln/detail/CVE-2004-2771 + if (!std::regex_match( + s, + std::regex("^[a-zA-Z0-9]" + "[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]*@[a-zA-Z0-9]" + "(?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9]" + "(?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$"))) { if (use_logging) { VLOG(1) << "Invalid destination email address:" << s; } else {