argsman: Prevent duplicate option registration across categories
What changed, and why it matters
This commit adds a safety check in Bitcoin Core's command-line option parser to prevent the same option name from being registered in more than one category. Previously, an option could accidentally be defined twice under different categories, which could lead to confusing or ambiguous behavior when the program tries to decide which definition applies. The change makes the program crash with an assertion failure during startup if such a duplicate is detected, turning a potential silent misconfiguration into an obvious failure.
No immediate action required. This is a hardening change. Developers should ensure no existing option names collide across categories, as the new assertion will cause debug/development builds to abort if a duplicate is present.
Security signals we found
Defensive assertion added to prevent ambiguous option resolution
Prevents cross-category duplicate option registration
Could mitigate misconfiguration or option-shadowing issues
Evidence from the diff
In ArgsManager::AddArg(), a loop now asserts that arg_name is not already present in any category within m_available_args before inserting it into the requested category. This prevents duplicate option registration across categories. The existing assert(ret.second) only caught duplicates within the same category; the new Assert() catches cross-category collisions. Because AddArg is typically called during static initialization or startup, this is a defensive hardening change rather than a runtime bug fix.
Changed components
src/common/args.cppArgsManager::AddArg()Inspect captured patch +5 / −0
diff --git a/src/common/args.cpp b/src/common/args.cpp
index c24ec491..4721a90b 100644
--- a/src/common/args.cpp
+++ b/src/common/args.cpp
@@ -668,6 +668,11 @@ void ArgsManager::AddArg(const std::string& name, const std::string& help, unsig
std::string arg_name = name.substr(0, eq_index);
LOCK(cs_args);
+
+ for (const auto& arg_map : m_available_args) {
+ Assert(!arg_map.second.contains(arg_name));
+ }
+
std::map<std::string, Arg>& arg_map = m_available_args[cat];
auto ret = arg_map.emplace(arg_name, Arg{name.substr(eq_index, name.size() - eq_index), help, flags});
assert(ret.second); // Make sure an insertion actually happened
Why this scored 35/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.