refactor: Remove unused Parse(U)Int*

This commit is contained in:
MarcoFalke
2025-05-15 22:33:51 +02:00
parent fa84e6c36c
commit 3333282933
5 changed files with 41 additions and 327 deletions

View File

@@ -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<int64_t>();
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<int32_t>();
(void)random_int32;
const std::string strprintf_int_without_locale = strprintf("%d", random_int64);
const double random_double = fuzzed_data_provider.ConsumeFloatingPoint<double>();
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);

View File

@@ -5,33 +5,59 @@
#include <test/fuzz/fuzz.h>
#include <util/moneystr.h>
#include <util/strencodings.h>
#include <util/string.h>
#include <cassert>
#include <cstdint>
#include <optional>
#include <string>
FUZZ_TARGET(parse_numbers)
{
const std::string random_string(buffer.begin(), buffer.end());
{
const auto i8{ToIntegral<int8_t>(random_string)};
const auto u8{ToIntegral<uint8_t>(random_string)};
const auto i16{ToIntegral<int16_t>(random_string)};
const auto u16{ToIntegral<uint16_t>(random_string)};
const auto i32{ToIntegral<int32_t>(random_string)};
const auto u32{ToIntegral<uint32_t>(random_string)};
const auto i64{ToIntegral<int64_t>(random_string)};
const auto u64{ToIntegral<uint64_t>(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<int>(random_string);
uint32_t u32;
(void)ParseUInt32(random_string, &u32);
int64_t i64;
(void)LocaleIndependentAtoi<int64_t>(random_string);
(void)ParseFixedPoint(random_string, 3, &i64);
(void)ParseInt64(random_string, &i64);
uint64_t u64;
(void)ParseUInt64(random_string, &u64);
}

View File

@@ -647,40 +647,6 @@ BOOST_AUTO_TEST_CASE(util_overflow)
TestAddMatrix<signed>();
}
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 <typename T>
static void RunToIntegralTests()
{
@@ -868,171 +834,6 @@ BOOST_AUTO_TEST_CASE(test_LocaleIndependentAtoi)
BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint8_t>("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<uint8_t>(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<uint16_t>(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), "");

View File

@@ -199,57 +199,6 @@ std::optional<std::vector<unsigned char>> DecodeBase32(std::string_view str)
return ret;
}
namespace {
template <typename T>
bool ParseIntegral(std::string_view str, T* out)
{
static_assert(std::is_integral_v<T>);
// 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<T> opt_int = ToIntegral<T>((!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<int32_t>(str, out);
}
bool ParseInt64(std::string_view str, int64_t* out)
{
return ParseIntegral<int64_t>(str, out);
}
bool ParseUInt8(std::string_view str, uint8_t* out)
{
return ParseIntegral<uint8_t>(str, out);
}
bool ParseUInt16(std::string_view str, uint16_t* out)
{
return ParseIntegral<uint16_t>(str, out);
}
bool ParseUInt32(std::string_view str, uint32_t* out)
{
return ParseIntegral<uint32_t>(str, out);
}
bool ParseUInt64(std::string_view str, uint64_t* out)
{
return ParseIntegral<uint64_t>(str, out);
}
std::string FormatParagraph(std::string_view in, size_t width, size_t indent)
{
assert(width >= indent);

View File

@@ -187,48 +187,6 @@ std::optional<T> 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.