diff --git a/src/test/fuzz/locale.cpp b/src/test/fuzz/locale.cpp index 68db8422477..c0289172696 100644 --- a/src/test/fuzz/locale.cpp +++ b/src/test/fuzz/locale.cpp @@ -46,16 +46,8 @@ FUZZ_TARGET(locale) assert(c_locale != nullptr); const std::string random_string = fuzzed_data_provider.ConsumeRandomLengthString(5); - int32_t parseint32_out_without_locale; - const bool parseint32_without_locale = ParseInt32(random_string, &parseint32_out_without_locale); - int64_t parseint64_out_without_locale; - const bool parseint64_without_locale = ParseInt64(random_string, &parseint64_out_without_locale); const int64_t random_int64 = fuzzed_data_provider.ConsumeIntegral(); const std::string tostring_without_locale = util::ToString(random_int64); - // The variable `random_int32` is no longer used, but the harness still needs to - // consume the same data that it did previously to not invalidate existing seeds. - const int32_t random_int32 = fuzzed_data_provider.ConsumeIntegral(); - (void)random_int32; const std::string strprintf_int_without_locale = strprintf("%d", random_int64); const double random_double = fuzzed_data_provider.ConsumeFloatingPoint(); const std::string strprintf_double_without_locale = strprintf("%f", random_double); @@ -63,18 +55,6 @@ FUZZ_TARGET(locale) const char* new_locale = std::setlocale(LC_ALL, locale_identifier.c_str()); assert(new_locale != nullptr); - int32_t parseint32_out_with_locale; - const bool parseint32_with_locale = ParseInt32(random_string, &parseint32_out_with_locale); - assert(parseint32_without_locale == parseint32_with_locale); - if (parseint32_without_locale) { - assert(parseint32_out_without_locale == parseint32_out_with_locale); - } - int64_t parseint64_out_with_locale; - const bool parseint64_with_locale = ParseInt64(random_string, &parseint64_out_with_locale); - assert(parseint64_without_locale == parseint64_with_locale); - if (parseint64_without_locale) { - assert(parseint64_out_without_locale == parseint64_out_with_locale); - } const std::string tostring_with_locale = util::ToString(random_int64); assert(tostring_without_locale == tostring_with_locale); const std::string strprintf_int_with_locale = strprintf("%d", random_int64); diff --git a/src/test/fuzz/parse_numbers.cpp b/src/test/fuzz/parse_numbers.cpp index 2cd31466790..6102647d695 100644 --- a/src/test/fuzz/parse_numbers.cpp +++ b/src/test/fuzz/parse_numbers.cpp @@ -5,33 +5,59 @@ #include #include #include +#include +#include +#include +#include #include FUZZ_TARGET(parse_numbers) { const std::string random_string(buffer.begin(), buffer.end()); + { + const auto i8{ToIntegral(random_string)}; + const auto u8{ToIntegral(random_string)}; + const auto i16{ToIntegral(random_string)}; + const auto u16{ToIntegral(random_string)}; + const auto i32{ToIntegral(random_string)}; + const auto u32{ToIntegral(random_string)}; + const auto i64{ToIntegral(random_string)}; + const auto u64{ToIntegral(random_string)}; + // Dont check any values, just that each success result must fit into + // the one with the largest bit-width. + if (i8) { + assert(i8 == i64); + } + if (u8) { + assert(u8 == u64); + } + if (i16) { + assert(i16 == i64); + } + if (u16) { + assert(u16 == u64); + } + if (i32) { + assert(i32 == i64); + } + if (u32) { + assert(u32 == u64); + } + constexpr auto digits{"0123456789"}; + if (i64) { + assert(util::RemovePrefixView(random_string, "-").find_first_not_of(digits) == std::string::npos); + } + if (u64) { + assert(random_string.find_first_not_of(digits) == std::string::npos); + } + } (void)ParseMoney(random_string); - uint8_t u8; - (void)ParseUInt8(random_string, &u8); - - uint16_t u16; - (void)ParseUInt16(random_string, &u16); - - int32_t i32; - (void)ParseInt32(random_string, &i32); (void)LocaleIndependentAtoi(random_string); - uint32_t u32; - (void)ParseUInt32(random_string, &u32); - int64_t i64; (void)LocaleIndependentAtoi(random_string); (void)ParseFixedPoint(random_string, 3, &i64); - (void)ParseInt64(random_string, &i64); - - uint64_t u64; - (void)ParseUInt64(random_string, &u64); } diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index dc0e630a225..4263dfa711b 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -647,40 +647,6 @@ BOOST_AUTO_TEST_CASE(util_overflow) TestAddMatrix(); } -BOOST_AUTO_TEST_CASE(test_ParseInt32) -{ - int32_t n; - // Valid values - BOOST_CHECK(ParseInt32("1234", nullptr)); - BOOST_CHECK(ParseInt32("0", &n) && n == 0); - BOOST_CHECK(ParseInt32("1234", &n) && n == 1234); - BOOST_CHECK(ParseInt32("01234", &n) && n == 1234); // no octal - BOOST_CHECK(ParseInt32("2147483647", &n) && n == 2147483647); - BOOST_CHECK(ParseInt32("-2147483648", &n) && n == (-2147483647 - 1)); // (-2147483647 - 1) equals INT_MIN - BOOST_CHECK(ParseInt32("-1234", &n) && n == -1234); - BOOST_CHECK(ParseInt32("00000000000000001234", &n) && n == 1234); - BOOST_CHECK(ParseInt32("-00000000000000001234", &n) && n == -1234); - BOOST_CHECK(ParseInt32("00000000000000000000", &n) && n == 0); - BOOST_CHECK(ParseInt32("-00000000000000000000", &n) && n == 0); - // Invalid values - BOOST_CHECK(!ParseInt32("", &n)); - BOOST_CHECK(!ParseInt32(" 1", &n)); // no padding inside - BOOST_CHECK(!ParseInt32("1 ", &n)); - BOOST_CHECK(!ParseInt32("++1", &n)); - BOOST_CHECK(!ParseInt32("+-1", &n)); - BOOST_CHECK(!ParseInt32("-+1", &n)); - BOOST_CHECK(!ParseInt32("--1", &n)); - BOOST_CHECK(!ParseInt32("1a", &n)); - BOOST_CHECK(!ParseInt32("aap", &n)); - BOOST_CHECK(!ParseInt32("0x1", &n)); // no hex - BOOST_CHECK(!ParseInt32(STRING_WITH_EMBEDDED_NULL_CHAR, &n)); - // Overflow and underflow - BOOST_CHECK(!ParseInt32("-2147483649", nullptr)); - BOOST_CHECK(!ParseInt32("2147483648", nullptr)); - BOOST_CHECK(!ParseInt32("-32482348723847471234", nullptr)); - BOOST_CHECK(!ParseInt32("32482348723847471234", nullptr)); -} - template static void RunToIntegralTests() { @@ -868,171 +834,6 @@ BOOST_AUTO_TEST_CASE(test_LocaleIndependentAtoi) BOOST_CHECK_EQUAL(LocaleIndependentAtoi("256"), 255U); } -BOOST_AUTO_TEST_CASE(test_ParseInt64) -{ - int64_t n; - // Valid values - BOOST_CHECK(ParseInt64("1234", nullptr)); - BOOST_CHECK(ParseInt64("0", &n) && n == 0LL); - BOOST_CHECK(ParseInt64("1234", &n) && n == 1234LL); - BOOST_CHECK(ParseInt64("01234", &n) && n == 1234LL); // no octal - BOOST_CHECK(ParseInt64("2147483647", &n) && n == 2147483647LL); - BOOST_CHECK(ParseInt64("-2147483648", &n) && n == -2147483648LL); - BOOST_CHECK(ParseInt64("9223372036854775807", &n) && n == int64_t{9223372036854775807}); - BOOST_CHECK(ParseInt64("-9223372036854775808", &n) && n == int64_t{-9223372036854775807-1}); - BOOST_CHECK(ParseInt64("-1234", &n) && n == -1234LL); - // Invalid values - BOOST_CHECK(!ParseInt64("", &n)); - BOOST_CHECK(!ParseInt64(" 1", &n)); // no padding inside - BOOST_CHECK(!ParseInt64("1 ", &n)); - BOOST_CHECK(!ParseInt64("1a", &n)); - BOOST_CHECK(!ParseInt64("aap", &n)); - BOOST_CHECK(!ParseInt64("0x1", &n)); // no hex - BOOST_CHECK(!ParseInt64(STRING_WITH_EMBEDDED_NULL_CHAR, &n)); - // Overflow and underflow - BOOST_CHECK(!ParseInt64("-9223372036854775809", nullptr)); - BOOST_CHECK(!ParseInt64("9223372036854775808", nullptr)); - BOOST_CHECK(!ParseInt64("-32482348723847471234", nullptr)); - BOOST_CHECK(!ParseInt64("32482348723847471234", nullptr)); -} - -BOOST_AUTO_TEST_CASE(test_ParseUInt8) -{ - uint8_t n; - // Valid values - BOOST_CHECK(ParseUInt8("255", nullptr)); - BOOST_CHECK(ParseUInt8("0", &n) && n == 0); - BOOST_CHECK(ParseUInt8("255", &n) && n == 255); - BOOST_CHECK(ParseUInt8("0255", &n) && n == 255); // no octal - BOOST_CHECK(ParseUInt8("255", &n) && n == static_cast(255)); - BOOST_CHECK(ParseUInt8("+255", &n) && n == 255); - BOOST_CHECK(ParseUInt8("00000000000000000012", &n) && n == 12); - BOOST_CHECK(ParseUInt8("00000000000000000000", &n) && n == 0); - // Invalid values - BOOST_CHECK(!ParseUInt8("-00000000000000000000", &n)); - BOOST_CHECK(!ParseUInt8("", &n)); - BOOST_CHECK(!ParseUInt8(" 1", &n)); // no padding inside - BOOST_CHECK(!ParseUInt8(" -1", &n)); - BOOST_CHECK(!ParseUInt8("++1", &n)); - BOOST_CHECK(!ParseUInt8("+-1", &n)); - BOOST_CHECK(!ParseUInt8("-+1", &n)); - BOOST_CHECK(!ParseUInt8("--1", &n)); - BOOST_CHECK(!ParseUInt8("-1", &n)); - BOOST_CHECK(!ParseUInt8("1 ", &n)); - BOOST_CHECK(!ParseUInt8("1a", &n)); - BOOST_CHECK(!ParseUInt8("aap", &n)); - BOOST_CHECK(!ParseUInt8("0x1", &n)); // no hex - BOOST_CHECK(!ParseUInt8(STRING_WITH_EMBEDDED_NULL_CHAR, &n)); - // Overflow and underflow - BOOST_CHECK(!ParseUInt8("-255", &n)); - BOOST_CHECK(!ParseUInt8("256", &n)); - BOOST_CHECK(!ParseUInt8("-123", &n)); - BOOST_CHECK(!ParseUInt8("-123", nullptr)); - BOOST_CHECK(!ParseUInt8("256", nullptr)); -} - -BOOST_AUTO_TEST_CASE(test_ParseUInt16) -{ - uint16_t n; - // Valid values - BOOST_CHECK(ParseUInt16("1234", nullptr)); - BOOST_CHECK(ParseUInt16("0", &n) && n == 0); - BOOST_CHECK(ParseUInt16("1234", &n) && n == 1234); - BOOST_CHECK(ParseUInt16("01234", &n) && n == 1234); // no octal - BOOST_CHECK(ParseUInt16("65535", &n) && n == static_cast(65535)); - BOOST_CHECK(ParseUInt16("+65535", &n) && n == 65535); - BOOST_CHECK(ParseUInt16("00000000000000000012", &n) && n == 12); - BOOST_CHECK(ParseUInt16("00000000000000000000", &n) && n == 0); - // Invalid values - BOOST_CHECK(!ParseUInt16("-00000000000000000000", &n)); - BOOST_CHECK(!ParseUInt16("", &n)); - BOOST_CHECK(!ParseUInt16(" 1", &n)); // no padding inside - BOOST_CHECK(!ParseUInt16(" -1", &n)); - BOOST_CHECK(!ParseUInt16("++1", &n)); - BOOST_CHECK(!ParseUInt16("+-1", &n)); - BOOST_CHECK(!ParseUInt16("-+1", &n)); - BOOST_CHECK(!ParseUInt16("--1", &n)); - BOOST_CHECK(!ParseUInt16("-1", &n)); - BOOST_CHECK(!ParseUInt16("1 ", &n)); - BOOST_CHECK(!ParseUInt16("1a", &n)); - BOOST_CHECK(!ParseUInt16("aap", &n)); - BOOST_CHECK(!ParseUInt16("0x1", &n)); // no hex - BOOST_CHECK(!ParseUInt16(STRING_WITH_EMBEDDED_NULL_CHAR, &n)); - // Overflow and underflow - BOOST_CHECK(!ParseUInt16("-65535", &n)); - BOOST_CHECK(!ParseUInt16("65536", &n)); - BOOST_CHECK(!ParseUInt16("-123", &n)); - BOOST_CHECK(!ParseUInt16("-123", nullptr)); - BOOST_CHECK(!ParseUInt16("65536", nullptr)); -} - -BOOST_AUTO_TEST_CASE(test_ParseUInt32) -{ - uint32_t n; - // Valid values - BOOST_CHECK(ParseUInt32("1234", nullptr)); - BOOST_CHECK(ParseUInt32("0", &n) && n == 0); - BOOST_CHECK(ParseUInt32("1234", &n) && n == 1234); - BOOST_CHECK(ParseUInt32("01234", &n) && n == 1234); // no octal - BOOST_CHECK(ParseUInt32("2147483647", &n) && n == 2147483647); - BOOST_CHECK(ParseUInt32("2147483648", &n) && n == uint32_t{2147483648}); - BOOST_CHECK(ParseUInt32("4294967295", &n) && n == uint32_t{4294967295}); - BOOST_CHECK(ParseUInt32("+1234", &n) && n == 1234); - BOOST_CHECK(ParseUInt32("00000000000000001234", &n) && n == 1234); - BOOST_CHECK(ParseUInt32("00000000000000000000", &n) && n == 0); - // Invalid values - BOOST_CHECK(!ParseUInt32("-00000000000000000000", &n)); - BOOST_CHECK(!ParseUInt32("", &n)); - BOOST_CHECK(!ParseUInt32(" 1", &n)); // no padding inside - BOOST_CHECK(!ParseUInt32(" -1", &n)); - BOOST_CHECK(!ParseUInt32("++1", &n)); - BOOST_CHECK(!ParseUInt32("+-1", &n)); - BOOST_CHECK(!ParseUInt32("-+1", &n)); - BOOST_CHECK(!ParseUInt32("--1", &n)); - BOOST_CHECK(!ParseUInt32("-1", &n)); - BOOST_CHECK(!ParseUInt32("1 ", &n)); - BOOST_CHECK(!ParseUInt32("1a", &n)); - BOOST_CHECK(!ParseUInt32("aap", &n)); - BOOST_CHECK(!ParseUInt32("0x1", &n)); // no hex - BOOST_CHECK(!ParseUInt32(STRING_WITH_EMBEDDED_NULL_CHAR, &n)); - // Overflow and underflow - BOOST_CHECK(!ParseUInt32("-2147483648", &n)); - BOOST_CHECK(!ParseUInt32("4294967296", &n)); - BOOST_CHECK(!ParseUInt32("-1234", &n)); - BOOST_CHECK(!ParseUInt32("-32482348723847471234", nullptr)); - BOOST_CHECK(!ParseUInt32("32482348723847471234", nullptr)); -} - -BOOST_AUTO_TEST_CASE(test_ParseUInt64) -{ - uint64_t n; - // Valid values - BOOST_CHECK(ParseUInt64("1234", nullptr)); - BOOST_CHECK(ParseUInt64("0", &n) && n == 0LL); - BOOST_CHECK(ParseUInt64("1234", &n) && n == 1234LL); - BOOST_CHECK(ParseUInt64("01234", &n) && n == 1234LL); // no octal - BOOST_CHECK(ParseUInt64("2147483647", &n) && n == 2147483647LL); - BOOST_CHECK(ParseUInt64("9223372036854775807", &n) && n == 9223372036854775807ULL); - BOOST_CHECK(ParseUInt64("9223372036854775808", &n) && n == 9223372036854775808ULL); - BOOST_CHECK(ParseUInt64("18446744073709551615", &n) && n == 18446744073709551615ULL); - // Invalid values - BOOST_CHECK(!ParseUInt64("", &n)); - BOOST_CHECK(!ParseUInt64(" 1", &n)); // no padding inside - BOOST_CHECK(!ParseUInt64(" -1", &n)); - BOOST_CHECK(!ParseUInt64("1 ", &n)); - BOOST_CHECK(!ParseUInt64("1a", &n)); - BOOST_CHECK(!ParseUInt64("aap", &n)); - BOOST_CHECK(!ParseUInt64("0x1", &n)); // no hex - BOOST_CHECK(!ParseUInt64(STRING_WITH_EMBEDDED_NULL_CHAR, &n)); - // Overflow and underflow - BOOST_CHECK(!ParseUInt64("-9223372036854775809", nullptr)); - BOOST_CHECK(!ParseUInt64("18446744073709551616", nullptr)); - BOOST_CHECK(!ParseUInt64("-32482348723847471234", nullptr)); - BOOST_CHECK(!ParseUInt64("-2147483648", &n)); - BOOST_CHECK(!ParseUInt64("-9223372036854775808", &n)); - BOOST_CHECK(!ParseUInt64("-1234", &n)); -} - BOOST_AUTO_TEST_CASE(test_FormatParagraph) { BOOST_CHECK_EQUAL(FormatParagraph("", 79, 0), ""); diff --git a/src/util/strencodings.cpp b/src/util/strencodings.cpp index 0c09915c8b4..289f49d46a7 100644 --- a/src/util/strencodings.cpp +++ b/src/util/strencodings.cpp @@ -199,57 +199,6 @@ std::optional> DecodeBase32(std::string_view str) return ret; } -namespace { -template -bool ParseIntegral(std::string_view str, T* out) -{ - static_assert(std::is_integral_v); - // Replicate the exact behavior of strtol/strtoll/strtoul/strtoull when - // handling leading +/- for backwards compatibility. - if (str.length() >= 2 && str[0] == '+' && str[1] == '-') { - return false; - } - const std::optional opt_int = ToIntegral((!str.empty() && str[0] == '+') ? str.substr(1) : str); - if (!opt_int) { - return false; - } - if (out != nullptr) { - *out = *opt_int; - } - return true; -} -}; // namespace - -bool ParseInt32(std::string_view str, int32_t* out) -{ - return ParseIntegral(str, out); -} - -bool ParseInt64(std::string_view str, int64_t* out) -{ - return ParseIntegral(str, out); -} - -bool ParseUInt8(std::string_view str, uint8_t* out) -{ - return ParseIntegral(str, out); -} - -bool ParseUInt16(std::string_view str, uint16_t* out) -{ - return ParseIntegral(str, out); -} - -bool ParseUInt32(std::string_view str, uint32_t* out) -{ - return ParseIntegral(str, out); -} - -bool ParseUInt64(std::string_view str, uint64_t* out) -{ - return ParseIntegral(str, out); -} - std::string FormatParagraph(std::string_view in, size_t width, size_t indent) { assert(width >= indent); diff --git a/src/util/strencodings.h b/src/util/strencodings.h index fd713a555c7..154a610dfb4 100644 --- a/src/util/strencodings.h +++ b/src/util/strencodings.h @@ -187,48 +187,6 @@ std::optional ToIntegral(std::string_view str) return result; } -/** - * Convert string to signed 32-bit integer with strict parse error feedback. - * @returns true if the entire string could be parsed as valid integer, - * false if not the entire string could be parsed or when overflow or underflow occurred. - */ -[[nodiscard]] bool ParseInt32(std::string_view str, int32_t *out); - -/** - * Convert string to signed 64-bit integer with strict parse error feedback. - * @returns true if the entire string could be parsed as valid integer, - * false if not the entire string could be parsed or when overflow or underflow occurred. - */ -[[nodiscard]] bool ParseInt64(std::string_view str, int64_t *out); - -/** - * Convert decimal string to unsigned 8-bit integer with strict parse error feedback. - * @returns true if the entire string could be parsed as valid integer, - * false if not the entire string could be parsed or when overflow or underflow occurred. - */ -[[nodiscard]] bool ParseUInt8(std::string_view str, uint8_t *out); - -/** - * Convert decimal string to unsigned 16-bit integer with strict parse error feedback. - * @returns true if the entire string could be parsed as valid integer, - * false if the entire string could not be parsed or if overflow or underflow occurred. - */ -[[nodiscard]] bool ParseUInt16(std::string_view str, uint16_t* out); - -/** - * Convert decimal string to unsigned 32-bit integer with strict parse error feedback. - * @returns true if the entire string could be parsed as valid integer, - * false if not the entire string could be parsed or when overflow or underflow occurred. - */ -[[nodiscard]] bool ParseUInt32(std::string_view str, uint32_t *out); - -/** - * Convert decimal string to unsigned 64-bit integer with strict parse error feedback. - * @returns true if the entire string could be parsed as valid integer, - * false if not the entire string could be parsed or when overflow or underflow occurred. - */ -[[nodiscard]] bool ParseUInt64(std::string_view str, uint64_t *out); - /** * Format a paragraph of text to a fixed width, adding spaces for * indentation to any added line.