util: reject out-of-range BIP32 keypath indices

ParseHDKeypath() parsed each path element with ToIntegral<uint32_t>, so
a bare decimal >= 2^31 (e.g. "m/2147483648" == 0x80000000) was silently
treated as "m/0h".

This commit rejects such overflow instead.
This commit is contained in:
Sjors Provoost
2026-07-01 11:43:16 +02:00
parent ba78c31a00
commit e36c4b76e1
2 changed files with 11 additions and 8 deletions

View File

@@ -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()

View File

@@ -45,6 +45,11 @@ bool ParseHDKeypath(const std::string& keypath_str, std::vector<uint32_t>& 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);