Files
bitcoin/src/util/bip32.cpp
Sjors Provoost e36c4b76e1 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.
2026-08-07 14:44:17 +02:00

75 lines
2.1 KiB
C++

// Copyright (c) 2019-present The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <util/bip32.h>
#include <tinyformat.h>
#include <util/strencodings.h>
#include <cstdint>
#include <cstdio>
#include <optional>
#include <sstream>
bool ParseHDKeypath(const std::string& keypath_str, std::vector<uint32_t>& keypath)
{
std::stringstream ss(keypath_str);
std::string item;
bool first = true;
while (std::getline(ss, item, '/') || std::getline(ss, item, 'h')) {
if (item.compare("m") == 0) {
if (first) {
first = false;
continue;
}
return false;
}
// Finds whether it is hardened
uint32_t path = 0;
size_t pos = item.find('\'');
if (pos == std::string::npos) {
pos = item.find('h');
}
if (pos != std::string::npos) {
// The hardened tick can only be in the last index of the string
if (pos != item.size() - 1) {
return false;
}
path |= 0x80000000;
item = item.substr(0, item.size() - 1); // Drop the last character which is the hardened tick
}
// Ensure this is only numbers
const auto number{ToIntegral<uint32_t>(item)};
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);
first = false;
}
return true;
}
std::string FormatHDKeypath(const std::vector<uint32_t>& path, bool apostrophe)
{
std::string ret;
for (auto i : path) {
ret += strprintf("/%i", (i << 1) >> 1);
if (i >> 31) ret += apostrophe ? '\'' : 'h';
}
return ret;
}
std::string WriteHDKeypath(const std::vector<uint32_t>& keypath, bool apostrophe)
{
return "m" + FormatHDKeypath(keypath, apostrophe);
}