string: add `base` argument for ToIntegral to operate on hexadecimal
What changed, and why it matters
This commit adds an optional new feature to a string-to-number helper so it can understand hexadecimal (base-16) input. It does not change existing behavior unless callers explicitly request base 16, and there is no indication it fixes a security bug or introduces a vulnerability.
No security action required. Treat as routine feature addition. Review future callers that use base 16 to ensure they validate input appropriately.
Security signals we found
No security-relevant signals in commit message or diff
Default behavior unchanged (base = 10)
Input validation remains strict (no leading/trailing characters, no 0x prefix)
No memory-unsafe operations or network/parsing surface changes
Evidence from the diff
The change extends the ToIntegral<T> template in src/util/strencodings.h with a defaulted size_t base = 10 parameter and passes it to std::from_chars. Existing callers continue to use base 10 by default. New unit tests verify hex parsing, including rejection of prefixes like 0xAB, whitespace, overflow, and signed/unsigned edge cases. The patch is purely additive and defensive.
Changed components
src/util/strencodings.hsrc/test/util_tests.cppInspect captured patch +37 / −3
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp
index 13821db4..daa5b8b3 100644
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -835,6 +835,39 @@ BOOST_AUTO_TEST_CASE(test_LocaleIndependentAtoi)
BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint8_t>("256"), 255U);
}
+BOOST_AUTO_TEST_CASE(test_ToIntegralHex)
+{
+ std::optional<uint64_t> n;
+ // Valid values
+ n = ToIntegral<uint64_t>("1234", 16);
+ BOOST_CHECK_EQUAL(*n, 0x1234);
+ n = ToIntegral<uint64_t>("a", 16);
+ BOOST_CHECK_EQUAL(*n, 0xA);
+ n = ToIntegral<uint64_t>("0000000a", 16);
+ BOOST_CHECK_EQUAL(*n, 0xA);
+ n = ToIntegral<uint64_t>("100", 16);
+ BOOST_CHECK_EQUAL(*n, 0x100);
+ n = ToIntegral<uint64_t>("DEADbeef", 16);
+ BOOST_CHECK_EQUAL(*n, 0xDEADbeef);
+ n = ToIntegral<uint64_t>("FfFfFfFf", 16);
+ BOOST_CHECK_EQUAL(*n, 0xFfFfFfFf);
+ n = ToIntegral<uint64_t>("123456789", 16);
+ BOOST_CHECK_EQUAL(*n, 0x123456789ULL);
+ n = ToIntegral<uint64_t>("0", 16);
+ BOOST_CHECK_EQUAL(*n, 0);
+ n = ToIntegral<uint64_t>("FfFfFfFfFfFfFfFf", 16);
+ BOOST_CHECK_EQUAL(*n, 0xFfFfFfFfFfFfFfFfULL);
+ n = ToIntegral<int64_t>("-1", 16);
+ BOOST_CHECK_EQUAL(*n, -1);
+ // Invalid values
+ BOOST_CHECK(!ToIntegral<uint64_t>("", 16));
+ BOOST_CHECK(!ToIntegral<uint64_t>("-1", 16));
+ BOOST_CHECK(!ToIntegral<uint64_t>("10 00", 16));
+ BOOST_CHECK(!ToIntegral<uint64_t>("1 ", 16));
+ BOOST_CHECK(!ToIntegral<uint64_t>("0xAB", 16));
+ BOOST_CHECK(!ToIntegral<uint64_t>("FfFfFfFfFfFfFfFf0", 16));
+}
+
BOOST_AUTO_TEST_CASE(test_FormatParagraph)
{
BOOST_CHECK_EQUAL(FormatParagraph("", 79, 0), "");
diff --git a/src/util/strencodings.h b/src/util/strencodings.h
index 01063858..dc8493ff 100644
--- a/src/util/strencodings.h
+++ b/src/util/strencodings.h
@@ -169,17 +169,18 @@ constexpr inline bool IsSpace(char c) noexcept {
/**
* Convert string to integral type T. Leading whitespace, a leading +, or any
* trailing character fail the parsing. The required format expressed as regex
- * is `-?[0-9]+`. The minus sign is only permitted for signed integer types.
+ * is `-?[0-9]+` by default (or `-?[0-9a-fA-F]+` if base = 16).
+ * The minus sign is only permitted for signed integer types.
*
* @returns std::nullopt if the entire string could not be parsed, or if the
* parsed value is not in the range representable by the type T.
*/
template <typename T>
-std::optional<T> ToIntegral(std::string_view str)
+std::optional<T> ToIntegral(std::string_view str, size_t base = 10)
{
static_assert(std::is_integral_v<T>);
T result;
- const auto [first_nonmatching, error_condition] = std::from_chars(str.data(), str.data() + str.size(), result);
+ const auto [first_nonmatching, error_condition] = std::from_chars(str.data(), str.data() + str.size(), result, base);
if (first_nonmatching != str.data() + str.size() || error_condition != std::errc{}) {
return std::nullopt;
}
Why this scored 16/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.