aboutsummaryrefslogtreecommitdiff
path: root/src/wallet
diff options
context:
space:
mode:
authorSebastian Falbesoner <sebastian.falbesoner@gmail.com>2022-11-08 01:03:07 +0100
committerSebastian Falbesoner <sebastian.falbesoner@gmail.com>2022-11-08 12:29:12 +0100
commit349ed2a0eed3aaaf199ead93057c97730869c3a3 (patch)
treee72d88e97bfa75f1c669c7359be10b5d017292f7 /src/wallet
parent50422b770a40f5fa964201d1e99fd6b5dc1653ca (diff)
downloadbitcoin-349ed2a0eed3aaaf199ead93057c97730869c3a3.tar.xz
wallet: throw error if legacy entries are present on loading descriptor wallets
In the wallet key-value-loading routine, most legacy type entries require a LegacyScriptPubKeyMan instance after successful deserialization. On a descriptor wallet, creating that (via method `GetOrCreateLegacyScriptPubKeyMan`) fails and then leads to a null-pointer dereference crash. Fix this by throwing an error if if the wallet flags indicate that we have a descriptor wallet and there is a legacy entry found.
Diffstat (limited to 'src/wallet')
-rw-r--r--src/wallet/wallet.cpp4
-rw-r--r--src/wallet/walletdb.cpp12
-rw-r--r--src/wallet/walletdb.h3
3 files changed, 18 insertions, 1 deletions
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 431e970edc..e0a3afcb94 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -2919,6 +2919,10 @@ std::shared_ptr<CWallet> CWallet::Create(WalletContext& context, const std::stri
"The wallet might had been created on a newer version.\n"
"Please try running the latest software version.\n"), walletFile);
return nullptr;
+ } else if (nLoadWalletRet == DBErrors::UNEXPECTED_LEGACY_ENTRY) {
+ error = strprintf(_("Unexpected legacy entry in descriptor wallet found. Loading wallet %s\n\n"
+ "The wallet might have been tampered with or created with malicious intent.\n"), walletFile);
+ return nullptr;
} else {
error = strprintf(_("Error loading %s"), walletFile);
return nullptr;
diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp
index 6a8f0d2481..3e4d2d64d2 100644
--- a/src/wallet/walletdb.cpp
+++ b/src/wallet/walletdb.cpp
@@ -315,6 +315,7 @@ public:
std::map<uint160, CHDChain> m_hd_chains;
bool tx_corrupt{false};
bool descriptor_unknown{false};
+ bool unexpected_legacy_entry{false};
CWalletScanState() = default;
};
@@ -332,6 +333,11 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
if (filter_fn && !filter_fn(strType)) {
return true;
}
+ // Legacy entries in descriptor wallets are not allowed, abort immediately
+ if (pwallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS) && DBKeys::LEGACY_TYPES.count(strType) > 0) {
+ wss.unexpected_legacy_entry = true;
+ return false;
+ }
if (strType == DBKeys::NAME) {
std::string strAddress;
ssKey >> strAddress;
@@ -833,6 +839,12 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
std::string strType, strErr;
if (!ReadKeyValue(pwallet, ssKey, ssValue, wss, strType, strErr))
{
+ if (wss.unexpected_legacy_entry) {
+ strErr = strprintf("Error: Unexpected legacy entry found in descriptor wallet %s. ", pwallet->GetName());
+ strErr += "The wallet might have been tampered with or created with malicious intent.";
+ pwallet->WalletLogPrintf("%s\n", strErr);
+ return DBErrors::UNEXPECTED_LEGACY_ENTRY;
+ }
// losing keys is considered a catastrophic error, anything else
// we assume the user can live with:
if (IsKeyType(strType) || strType == DBKeys::DEFAULTKEY) {
diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h
index da6efe534b..27b5dbdd96 100644
--- a/src/wallet/walletdb.h
+++ b/src/wallet/walletdb.h
@@ -52,7 +52,8 @@ enum class DBErrors
LOAD_FAIL,
NEED_REWRITE,
NEED_RESCAN,
- UNKNOWN_DESCRIPTOR
+ UNKNOWN_DESCRIPTOR,
+ UNEXPECTED_LEGACY_ENTRY
};
namespace DBKeys {