diff options
Diffstat (limited to 'src/util/strencodings.h')
-rw-r--r-- | src/util/strencodings.h | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/src/util/strencodings.h b/src/util/strencodings.h index 0945556b5e..1f83fa3ffa 100644 --- a/src/util/strencodings.h +++ b/src/util/strencodings.h @@ -16,6 +16,7 @@ #include <charconv> #include <cstdint> #include <iterator> +#include <limits> #include <optional> #include <string> #include <vector> @@ -93,8 +94,12 @@ void SplitHostPort(std::string in, uint16_t& portOut, std::string& hostOut); // New code should use ToIntegral or the ParseInt* functions // which provide parse error feedback. // -// The goal of LocaleIndependentAtoi is to replicate the exact defined behaviour -// of atoi and atoi64 as they behave under the "C" locale. +// The goal of LocaleIndependentAtoi is to replicate the defined behaviour of +// std::atoi as it behaves under the "C" locale, and remove some undefined +// behavior. If the parsed value is bigger than the integer type's maximum +// value, or smaller than the integer type's minimum value, std::atoi has +// undefined behavior, while this function returns the maximum or minimum +// values, respectively. template <typename T> T LocaleIndependentAtoi(const std::string& str) { @@ -109,7 +114,15 @@ T LocaleIndependentAtoi(const std::string& str) s = s.substr(1); } auto [_, error_condition] = std::from_chars(s.data(), s.data() + s.size(), result); - if (error_condition != std::errc{}) { + if (error_condition == std::errc::result_out_of_range) { + if (s.length() >= 1 && s[0] == '-') { + // Saturate underflow, per strtoll's behavior. + return std::numeric_limits<T>::min(); + } else { + // Saturate overflow, per strtoll's behavior. + return std::numeric_limits<T>::max(); + } + } else if (error_condition != std::errc{}) { return 0; } return result; |