From e36c4b76e198751c14da8d32655e47bd5678abb6 Mon Sep 17 00:00:00 2001 From: Sjors Provoost Date: Wed, 1 Jul 2026 11:43:16 +0200 Subject: [PATCH] util: reject out-of-range BIP32 keypath indices ParseHDKeypath() parsed each path element with ToIntegral, so a bare decimal >= 2^31 (e.g. "m/2147483648" == 0x80000000) was silently treated as "m/0h". This commit rejects such overflow instead. --- src/test/bip32_tests.cpp | 14 ++++++-------- src/util/bip32.cpp | 5 +++++ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/test/bip32_tests.cpp b/src/test/bip32_tests.cpp index 3f13cd6ebe9..daa03a6679b 100644 --- a/src/test/bip32_tests.cpp +++ b/src/test/bip32_tests.cpp @@ -265,8 +265,12 @@ BOOST_AUTO_TEST_CASE(parse_hd_keypath) BOOST_CHECK(ParseHDKeypath("42", keypath)); BOOST_CHECK(!ParseHDKeypath("m42", keypath)); - BOOST_CHECK(ParseHDKeypath("4294967295", keypath)); // 4294967295 == 0xFFFFFFFF (uint32_t max) - BOOST_CHECK(!ParseHDKeypath("4294967296", keypath)); // 4294967296 == 0xFFFFFFFF (uint32_t max) + 1 + // A path element's numeric part is capped at 2^31-1; the top bit is + // reserved for the hardened marker (h or '). + BOOST_CHECK(ParseHDKeypath("2147483647", keypath)); // 0x7fffffff, largest normal index + BOOST_CHECK(!ParseHDKeypath("2147483648", keypath)); // 0x80000000, would set the hardened bit + BOOST_CHECK(!ParseHDKeypath("4294967295", keypath)); // 0xffffffff + BOOST_CHECK(!ParseHDKeypath("4294967296", keypath)); // uint32_t max + 1 BOOST_CHECK(ParseHDKeypath("m", keypath)); BOOST_CHECK(!ParseHDKeypath("n", keypath)); @@ -306,12 +310,6 @@ BOOST_AUTO_TEST_CASE(parse_hd_keypath) BOOST_CHECK(ParseHDKeypath("m/1/", keypath)); BOOST_CHECK(!ParseHDKeypath("m/1//", keypath)); - - BOOST_CHECK(ParseHDKeypath("m/0/4294967295", keypath)); // 4294967295 == 0xFFFFFFFF (uint32_t max) - BOOST_CHECK(!ParseHDKeypath("m/0/4294967296", keypath)); // 4294967296 == 0xFFFFFFFF (uint32_t max) + 1 - - BOOST_CHECK(ParseHDKeypath("m/4294967295", keypath)); // 4294967295 == 0xFFFFFFFF (uint32_t max) - BOOST_CHECK(!ParseHDKeypath("m/4294967296", keypath)); // 4294967296 == 0xFFFFFFFF (uint32_t max) + 1 } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/util/bip32.cpp b/src/util/bip32.cpp index 5f0ca221f52..475fac60a46 100644 --- a/src/util/bip32.cpp +++ b/src/util/bip32.cpp @@ -45,6 +45,11 @@ bool ParseHDKeypath(const std::string& keypath_str, std::vector& keypa if (!number) { return false; } + // A BIP32 child index is 31 bits; the top bit is reserved for the + // hardened marker, so the numeric part must not exceed 2^31 - 1. + if (*number > 0x7fffffff) { + return false; + } path |= *number; keypath.push_back(path);