From 335ff98c8a64eda38a2a2334102bd253f108c253 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Sun, 4 Sep 2022 21:28:55 +0000 Subject: [PATCH 1/2] Bugfix: Wallet: Wrap RestoreWallet content in a try block to ensure exceptions become returned errors and incomplete wallet directory is removed --- src/wallet/wallet.cpp | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index de1078e646453..1994ac2171c89 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -379,25 +379,31 @@ std::shared_ptr RestoreWallet(WalletContext& context, const fs::path& b ReadDatabaseArgs(*context.args, options); options.require_existing = true; - if (!fs::exists(backup_file)) { - error = Untranslated("Backup file does not exist"); - status = DatabaseStatus::FAILED_INVALID_BACKUP_FILE; - return nullptr; - } - const fs::path wallet_path = fsbridge::AbsPathJoin(GetWalletDir(), fs::u8path(wallet_name)); + auto wallet_file = wallet_path / "wallet.dat"; + std::shared_ptr wallet; - if (fs::exists(wallet_path) || !TryCreateDirectories(wallet_path)) { - error = Untranslated(strprintf("Failed to create database path '%s'. Database already exists.", fs::PathToString(wallet_path))); - status = DatabaseStatus::FAILED_ALREADY_EXISTS; - return nullptr; - } + try { + if (!fs::exists(backup_file)) { + error = Untranslated("Backup file does not exist"); + status = DatabaseStatus::FAILED_INVALID_BACKUP_FILE; + return nullptr; + } - auto wallet_file = wallet_path / "wallet.dat"; - fs::copy_file(backup_file, wallet_file, fs::copy_options::none); + if (fs::exists(wallet_path) || !TryCreateDirectories(wallet_path)) { + error = Untranslated(strprintf("Failed to create database path '%s'. Database already exists.", fs::PathToString(wallet_path))); + status = DatabaseStatus::FAILED_ALREADY_EXISTS; + return nullptr; + } - auto wallet = LoadWallet(context, wallet_name, load_on_start, options, status, error, warnings); + fs::copy_file(backup_file, wallet_file, fs::copy_options::none); + wallet = LoadWallet(context, wallet_name, load_on_start, options, status, error, warnings); + } catch (const std::exception& e) { + assert(!wallet); + if (!error.empty()) error += Untranslated("\n"); + error += strprintf(Untranslated("Unexpected exception: %s"), e.what()); + } if (!wallet) { fs::remove(wallet_file); fs::remove(wallet_path); From c3e536555aa3a7db773170671da1256a2ace2094 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Sun, 4 Sep 2022 21:29:07 +0000 Subject: [PATCH 2/2] Bugfix: Wallet: Return util::Error rather than non-error nullptr when CreateWallet/LoadWallet/RestoreWallet fail --- src/wallet/interfaces.cpp | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/wallet/interfaces.cpp b/src/wallet/interfaces.cpp index 4fbc519e39471..1650a9e5eee66 100644 --- a/src/wallet/interfaces.cpp +++ b/src/wallet/interfaces.cpp @@ -560,8 +560,12 @@ class WalletLoaderImpl : public WalletLoader options.create_flags = wallet_creation_flags; options.create_passphrase = passphrase; bilingual_str error; - util::Result> wallet{MakeWallet(m_context, CreateWallet(m_context, name, /*load_on_start=*/true, options, status, error, warnings))}; - return wallet ? std::move(wallet) : util::Error{error}; + std::unique_ptr wallet{MakeWallet(m_context, CreateWallet(m_context, name, /*load_on_start=*/true, options, status, error, warnings))}; + if (wallet) { + return {std::move(wallet)}; + } else { + return util::Error{error}; + } } util::Result> loadWallet(const std::string& name, std::vector& warnings) override { @@ -570,15 +574,23 @@ class WalletLoaderImpl : public WalletLoader ReadDatabaseArgs(*m_context.args, options); options.require_existing = true; bilingual_str error; - util::Result> wallet{MakeWallet(m_context, LoadWallet(m_context, name, /*load_on_start=*/true, options, status, error, warnings))}; - return wallet ? std::move(wallet) : util::Error{error}; + std::unique_ptr wallet{MakeWallet(m_context, LoadWallet(m_context, name, /*load_on_start=*/true, options, status, error, warnings))}; + if (wallet) { + return {std::move(wallet)}; + } else { + return util::Error{error}; + } } util::Result> restoreWallet(const fs::path& backup_file, const std::string& wallet_name, std::vector& warnings) override { DatabaseStatus status; bilingual_str error; - util::Result> wallet{MakeWallet(m_context, RestoreWallet(m_context, backup_file, wallet_name, /*load_on_start=*/true, status, error, warnings))}; - return wallet ? std::move(wallet) : util::Error{error}; + std::unique_ptr wallet{MakeWallet(m_context, RestoreWallet(m_context, backup_file, wallet_name, /*load_on_start=*/true, status, error, warnings))}; + if (wallet) { + return {std::move(wallet)}; + } else { + return util::Error{error}; + } } std::string getWalletDir() override {