qt: Avoid crash on startup if int specified in settings.json

Fix GUI startup crash reported by Rspigler in
https://github.com/bitcoin/bitcoin/issues/24457 that happens if
settings.json contains an integer value for any of the configuration
options which GUI settings can currently clash with (-dbcache, -par,
-spendzeroconfchange, -signer, -upnp, -natpmp, -listen, -server, -proxy,
-proxy, -onion, -onion, -lang, and -prune).

Fix is a one-line change in ArgsManager::GetArg.

Github-Pull: bitcoin/bitcoin#24498
Rebased-From: 5b1aae12ca
This commit is contained in:
Ryan Ofsky 2022-03-07 13:29:46 -05:00 committed by Andrew Chow
parent 4607f700d0
commit 7e1b968f61
No known key found for this signature in database
GPG key ID: 17565732E08E5E41
3 changed files with 8 additions and 8 deletions

View file

@ -15,15 +15,15 @@
//! Entry point for BitcoinApplication tests. //! Entry point for BitcoinApplication tests.
void OptionTests::optionTests() void OptionTests::optionTests()
{ {
// Test regression https://github.com/bitcoin/bitcoin/issues/24457. Check // Test regression https://github.com/bitcoin/bitcoin/issues/24457. Ensure
// if setting an integer prune value causes an exception to be thrown in // that setting integer prune value doesn't cause an exception to be thrown
// the OptionsModel constructor. // in the OptionsModel constructor
gArgs.LockSettings([&](util::Settings& settings) { gArgs.LockSettings([&](util::Settings& settings) {
settings.forced_settings.erase("prune"); settings.forced_settings.erase("prune");
settings.rw_settings["prune"] = 3814; settings.rw_settings["prune"] = 3814;
}); });
gArgs.WriteSettingsFile(); gArgs.WriteSettingsFile();
QVERIFY_EXCEPTION_THROWN(OptionsModel{}, std::runtime_error); OptionsModel{};
gArgs.LockSettings([&](util::Settings& settings) { gArgs.LockSettings([&](util::Settings& settings) {
settings.rw_settings.erase("prune"); settings.rw_settings.erase("prune");
}); });

View file

@ -98,21 +98,21 @@ BOOST_AUTO_TEST_CASE(setting_args)
set_foo(99); set_foo(99);
BOOST_CHECK_EQUAL(args.GetSetting("foo").write(), "99"); BOOST_CHECK_EQUAL(args.GetSetting("foo").write(), "99");
BOOST_CHECK_THROW(args.GetArg("foo", "default"), std::runtime_error); BOOST_CHECK_EQUAL(args.GetArg("foo", "default"), "99");
BOOST_CHECK_EQUAL(args.GetIntArg("foo", 100), 99); BOOST_CHECK_EQUAL(args.GetIntArg("foo", 100), 99);
BOOST_CHECK_THROW(args.GetBoolArg("foo", true), std::runtime_error); BOOST_CHECK_THROW(args.GetBoolArg("foo", true), std::runtime_error);
BOOST_CHECK_THROW(args.GetBoolArg("foo", false), std::runtime_error); BOOST_CHECK_THROW(args.GetBoolArg("foo", false), std::runtime_error);
set_foo(3.25); set_foo(3.25);
BOOST_CHECK_EQUAL(args.GetSetting("foo").write(), "3.25"); BOOST_CHECK_EQUAL(args.GetSetting("foo").write(), "3.25");
BOOST_CHECK_THROW(args.GetArg("foo", "default"), std::runtime_error); BOOST_CHECK_EQUAL(args.GetArg("foo", "default"), "3.25");
BOOST_CHECK_THROW(args.GetIntArg("foo", 100), std::runtime_error); BOOST_CHECK_THROW(args.GetIntArg("foo", 100), std::runtime_error);
BOOST_CHECK_THROW(args.GetBoolArg("foo", true), std::runtime_error); BOOST_CHECK_THROW(args.GetBoolArg("foo", true), std::runtime_error);
BOOST_CHECK_THROW(args.GetBoolArg("foo", false), std::runtime_error); BOOST_CHECK_THROW(args.GetBoolArg("foo", false), std::runtime_error);
set_foo(0); set_foo(0);
BOOST_CHECK_EQUAL(args.GetSetting("foo").write(), "0"); BOOST_CHECK_EQUAL(args.GetSetting("foo").write(), "0");
BOOST_CHECK_THROW(args.GetArg("foo", "default"), std::runtime_error); BOOST_CHECK_EQUAL(args.GetArg("foo", "default"), "0");
BOOST_CHECK_EQUAL(args.GetIntArg("foo", 100), 0); BOOST_CHECK_EQUAL(args.GetIntArg("foo", 100), 0);
BOOST_CHECK_THROW(args.GetBoolArg("foo", true), std::runtime_error); BOOST_CHECK_THROW(args.GetBoolArg("foo", true), std::runtime_error);
BOOST_CHECK_THROW(args.GetBoolArg("foo", false), std::runtime_error); BOOST_CHECK_THROW(args.GetBoolArg("foo", false), std::runtime_error);

View file

@ -588,7 +588,7 @@ bool ArgsManager::IsArgNegated(const std::string& strArg) const
std::string ArgsManager::GetArg(const std::string& strArg, const std::string& strDefault) const std::string ArgsManager::GetArg(const std::string& strArg, const std::string& strDefault) const
{ {
const util::SettingsValue value = GetSetting(strArg); const util::SettingsValue value = GetSetting(strArg);
return value.isNull() ? strDefault : value.isFalse() ? "0" : value.isTrue() ? "1" : value.get_str(); return value.isNull() ? strDefault : value.isFalse() ? "0" : value.isTrue() ? "1" : value.isNum() ? value.getValStr() : value.get_str();
} }
int64_t ArgsManager::GetIntArg(const std::string& strArg, int64_t nDefault) const int64_t ArgsManager::GetIntArg(const std::string& strArg, int64_t nDefault) const