mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-11-12 06:58:57 +01:00
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>
This commit is contained in:
committed by
Ryan Ofsky
parent
c561f2f06e
commit
b5c9bb5cb9
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user