Skip to content

Commit e334f7a

Browse files
committed
Merge bitcoin/bitcoin#26594: wallet: Avoid a segfault in migratewallet failure cleanup
5e65a21 wallet: Explicitly say migratewallet on encrypted wallets is unsupported (Andrew Chow) 88afc73 tests: Test for migrating encrypted wallets (Andrew Chow) 86ef7b3 wallet: Avoid null pointer deref when cleaning up migratewallet (Andrew Chow) Pull request description: When `migratewallet` fails, we do an automatic cleanup in order to reset everything so that the user does not experience any interruptions. However, this apparently has a segfault in it, caused by the the pointers to the watchonly and solvables wallets being nullptr. If those wallets are not created (either not needed, or failed early on), we will accidentally attempt to dereference these nullptrs, which causes a segfault. This failure can be easily reached by trying to migrate an encrypted wallet. Currently, we can't migrate encrypted wallets because of how we unload wallets before migrating, and therefore forget the encryption key if the wallet was unlocked. So any encrypted wallets will fail, entering the cleanup, and because watchonly and solvables wallets don't exist yet, the segfault is reached. This PR fixes this by not putting those nullptrs in a place that we will end up dereferencing them later. It also adds a test that uses the encrypted wallet issue. ACKs for top commit: S3RK: reACK 5e65a21 stickies-v: ACK [5e65a21](bitcoin/bitcoin@5e65a21) furszy: diff ACK 5e65a21 Tree-SHA512: f75643797220d4232ad3ab8cb4b46d0f3667f00486e910ca748c9b6d174d446968f1ec4dd7f907da1be9566088849da7edcd8cd8f12de671c3241b513deb8e80
2 parents e2bfd41 + 5e65a21 commit e334f7a

File tree

3 files changed

+15
-3
lines changed

3 files changed

+15
-3
lines changed

src/wallet/rpc/wallet.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -730,7 +730,9 @@ static RPCHelpMan migratewallet()
730730
std::shared_ptr<CWallet> wallet = GetWalletForJSONRPCRequest(request);
731731
if (!wallet) return NullUniValue;
732732

733-
EnsureWalletIsUnlocked(*wallet);
733+
if (wallet->IsCrypted()) {
734+
throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: migratewallet on encrypted wallets is currently unsupported.");
735+
}
734736

735737
WalletContext& context = EnsureWalletContext(request.context);
736738

src/wallet/wallet.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4182,8 +4182,8 @@ util::Result<MigrationResult> MigrateLegacyToDescriptor(std::shared_ptr<CWallet>
41824182

41834183
// Make list of wallets to cleanup
41844184
std::vector<std::shared_ptr<CWallet>> created_wallets;
4185-
created_wallets.push_back(std::move(res.watchonly_wallet));
4186-
created_wallets.push_back(std::move(res.solvables_wallet));
4185+
if (res.watchonly_wallet) created_wallets.push_back(std::move(res.watchonly_wallet));
4186+
if (res.solvables_wallet) created_wallets.push_back(std::move(res.solvables_wallet));
41874187

41884188
// Get the directories to remove after unloading
41894189
for (std::shared_ptr<CWallet>& w : created_wallets) {

test/functional/wallet_migration.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,15 @@ def test_pk_coinbases(self):
396396

397397
assert_equal(bals, wallet.getbalances())
398398

399+
def test_encrypted(self):
400+
self.log.info("Test migration of an encrypted wallet")
401+
wallet = self.create_legacy_wallet("encrypted")
402+
403+
wallet.encryptwallet("pass")
404+
405+
assert_raises_rpc_error(-15, "Error: migratewallet on encrypted wallets is currently unsupported.", wallet.migratewallet)
406+
# TODO: Fix migratewallet so that we can actually migrate encrypted wallets
407+
399408
def run_test(self):
400409
self.generate(self.nodes[0], 101)
401410

@@ -405,6 +414,7 @@ def run_test(self):
405414
self.test_other_watchonly()
406415
self.test_no_privkeys()
407416
self.test_pk_coinbases()
417+
self.test_encrypted()
408418

409419
if __name__ == '__main__':
410420
WalletMigrationTest().main()

0 commit comments

Comments
 (0)