aboutsummaryrefslogtreecommitdiff
path: root/src/util/strencodings.h
diff options
context:
space:
mode:
authorJames O'Beirne <james.obeirne@pm.me>2021-12-22 12:11:13 -0500
committerRyan Ofsky <ryan@ofsky.org>2022-01-11 19:54:36 -0500
commitb5c9bb5cb9f4a8db57b33ef7399310c7d6de5822 (patch)
tree005cf7c5a83f7f72aca4c10664483bd4b4ae361a /src/util/strencodings.h
parentc561f2f06ed25f08f7776ac41aeb2999ebe79550 (diff)
downloadbitcoin-b5c9bb5cb9f4a8db57b33ef7399310c7d6de5822.tar.xz
util: Restore GetIntArg saturating behavior
The new locale-independent atoi64 method introduced in #20452 parses large integer values higher than maximum representable value as 0 instead of the maximum value, which breaks backwards compatibility. This commit restores compatibility and adds test coverage for this case in terms of the related GetIntArg and strtoll functions. Co-authored-by: Ryan Ofsky <ryan@ofsky.org>
Diffstat (limited to 'src/util/strencodings.h')
-rw-r--r--src/util/strencodings.h19
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;