Skip to content

Commit 1ca76bc

Browse files
laanwjvijaydasmp
authored andcommitted
Merge bitcoin#14708: Warn unrecognised sections in the config file
3fb09b9 Warn unrecognized sections in the config file (Akio Nakamura) Pull request description: This PR intends to resolve bitcoin#14702. In the config file, sections are specified by square bracket pair "[]"$, or included in the option name itself which separated by a period"(.)". Typicaly, [testnet] is not a correct section name and specified options in that section are ignored but user cannot recognize what is happen. So, add some log-warning messages if unrecognized section names are present in the config file after checking section only args. note: Currentry, followings are out of scope of this PR. 1) Empty section name or option name can describe. e.g. [] , .a=b, =c 2) Multiple period characters can exist in the section name and option name. e.g. [c.d.e], [..], f.g.h.i=j, ..=k Tree-SHA512: 2cea02a0525feb40320613989a75cd7b7b1bd12158d5e6f3174ca77e6a25bb84425dd8812f62483df9fc482045c7b5402d69bc714430518b1847d055a2dc304b
1 parent 0c122a3 commit 1ca76bc

File tree

4 files changed

+57
-9
lines changed

4 files changed

+57
-9
lines changed

src/init.cpp

+9-1
Original file line numberDiff line numberDiff line change
@@ -1124,7 +1124,15 @@ void InitParameterInteraction()
11241124
// Warn if network-specific options (-addnode, -connect, etc) are
11251125
// specified in default section of config file, but not overridden
11261126
// on the command line or in this network's section of the config file.
1127-
gArgs.WarnForSectionOnlyArgs();
1127+
std::string network = gArgs.GetChainName();
1128+
for (const auto& arg : gArgs.GetUnsuitableSectionOnlyArgs()) {
1129+
InitWarning(strprintf(_("Config setting for %s only applied on %s network when in [%s] section."), arg, network, network));
1130+
}
1131+
1132+
// Warn if unrecognized section name are present in the config file.
1133+
for (const auto& section : gArgs.GetUnrecognizedSections()) {
1134+
InitWarning(strprintf(_("Section [%s] is not recognized."), section));
1135+
}
11281136
}
11291137

11301138
static std::string ResolveErrMsg(const char * const optname, const std::string& strBind)

src/util/system.cpp

+36-7
Original file line numberDiff line numberDiff line change
@@ -400,15 +400,17 @@ ArgsManager::ArgsManager() :
400400
// nothing to do
401401
}
402402

403-
void ArgsManager::WarnForSectionOnlyArgs()
403+
const std::set<std::string> ArgsManager::GetUnsuitableSectionOnlyArgs() const
404404
{
405+
std::set<std::string> unsuitables;
406+
405407
LOCK(cs_args);
406408

407409
// if there's no section selected, don't worry
408-
if (m_network.empty()) return;
410+
if (m_network.empty()) return std::set<std::string> {};
409411

410412
// if it's okay to use the default section for this network, don't worry
411-
if (m_network == CBaseChainParams::MAIN) return;
413+
if (m_network == CBaseChainParams::MAIN) return std::set<std::string> {};
412414

413415
for (const auto& arg : m_network_only_args) {
414416
std::pair<bool, std::string> found_result;
@@ -426,8 +428,29 @@ void ArgsManager::WarnForSectionOnlyArgs()
426428
if (!found_result.first) continue;
427429

428430
// otherwise, issue a warning
429-
LogPrintf("Warning: Config setting for %s only applied on %s network when in [%s] section.\n", arg, m_network, m_network);
431+
unsuitables.insert(arg);
430432
}
433+
return unsuitables;
434+
}
435+
436+
437+
const std::set<std::string> ArgsManager::GetUnrecognizedSections() const
438+
{
439+
// Section names to be recognized in the config file.
440+
static const std::set<std::string> available_sections{
441+
CBaseChainParams::REGTEST,
442+
CBaseChainParams::TESTNET,
443+
CBaseChainParams::MAIN,
444+
CBaseChainParams::DEVNET
445+
};
446+
std::set<std::string> diff;
447+
448+
LOCK(cs_args);
449+
std::set_difference(
450+
m_config_sections.begin(), m_config_sections.end(),
451+
available_sections.begin(), available_sections.end(),
452+
std::inserter(diff, diff.end()));
453+
return diff;
431454
}
432455

433456
void ArgsManager::SelectConfigNetwork(const std::string& network)
@@ -888,7 +911,7 @@ static std::string TrimString(const std::string& str, const std::string& pattern
888911
return str.substr(front, end - front + 1);
889912
}
890913

891-
static bool GetConfigOptions(std::istream& stream, std::string& error, std::vector<std::pair<std::string, std::string>> &options)
914+
static bool GetConfigOptions(std::istream& stream, std::string& error, std::vector<std::pair<std::string, std::string>>& options, std::set<std::string>& sections)
892915
{
893916
std::string str, prefix;
894917
std::string::size_type pos;
@@ -903,7 +926,9 @@ static bool GetConfigOptions(std::istream& stream, std::string& error, std::vect
903926
str = TrimString(str, pattern);
904927
if (!str.empty()) {
905928
if (*str.begin() == '[' && *str.rbegin() == ']') {
906-
prefix = str.substr(1, str.size() - 2) + '.';
929+
const std::string section = str.substr(1, str.size() - 2);
930+
sections.insert(section);
931+
prefix = section + '.';
907932
} else if (*str.begin() == '-') {
908933
error = strprintf("parse error on line %i: %s, options in configuration file must be specified without leading -", linenr, str);
909934
return false;
@@ -915,6 +940,9 @@ static bool GetConfigOptions(std::istream& stream, std::string& error, std::vect
915940
return false;
916941
}
917942
options.emplace_back(name, value);
943+
if ((pos = name.rfind('.')) != std::string::npos) {
944+
sections.insert(name.substr(0, pos));
945+
}
918946
} else {
919947
error = strprintf("parse error on line %i: %s", linenr, str);
920948
if (str.size() >= 2 && str.substr(0, 2) == "no") {
@@ -932,7 +960,8 @@ bool ArgsManager::ReadConfigStream(std::istream& stream, std::string& error, boo
932960
{
933961
LOCK(cs_args);
934962
std::vector<std::pair<std::string, std::string>> options;
935-
if (!GetConfigOptions(stream, error, options)) {
963+
m_config_sections.clear();
964+
if (!GetConfigOptions(stream, error, options, m_config_sections)) {
936965
return false;
937966
}
938967
for (const std::pair<std::string, std::string>& option : options) {

src/util/system.h

+7-1
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ class ArgsManager
178178
std::string m_network GUARDED_BY(cs_args);
179179
std::set<std::string> m_network_only_args GUARDED_BY(cs_args);
180180
std::map<OptionsCategory, std::map<std::string, Arg>> m_available_args GUARDED_BY(cs_args);
181+
std::set<std::string> m_config_sections GUARDED_BY(cs_args);
181182

182183
[[nodiscard]] bool ReadConfigStream(std::istream& stream, std::string& error, bool ignore_invalid_keys = false);
183184

@@ -198,7 +199,12 @@ class ArgsManager
198199
* on the command line or in a network-specific section in the
199200
* config file.
200201
*/
201-
void WarnForSectionOnlyArgs();
202+
const std::set<std::string> GetUnsuitableSectionOnlyArgs() const;
203+
204+
/**
205+
* Log warnings for unrecognized section names in the config file.
206+
*/
207+
const std::set<std::string> GetUnrecognizedSections() const;
202208

203209
/**
204210
* Return a vector of strings of the given argument

test/functional/feature_config_args.py

+5
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ def test_config_file_parser(self):
4343
conf.write('server=1\nrpcuser=someuser\nrpcpassword=some#pass')
4444
self.nodes[0].assert_start_raises_init_error(expected_msg='Error reading configuration file: parse error on line 3, using # in rpcpassword can be ambiguous and should be avoided')
4545

46+
with open(inc_conf_file_path, 'w', encoding='utf-8') as conf:
47+
conf.write('testnot.datadir=1\n[testnet]\n')
48+
self.restart_node(0)
49+
self.nodes[0].stop_node(expected_stderr='Warning: Section [testnet] is not recognized.' + os.linesep + 'Warning: Section [testnot] is not recognized.')
50+
4651
with open(inc_conf_file_path, 'w', encoding='utf-8') as conf:
4752
conf.write('') # clear
4853

0 commit comments

Comments
 (0)