#17580 refactor: Add ALLOW_LIST flags and enforce usage in CheckArgFlags

ReviewabilityReviewsAgreementSize
#17580 ryanofsky refactor: Add ALLOW_LIST flags and enforce usage in CheckArgFlagsReview #16545 first0Strong378 + 767 tests
  • Prevent subtle argument parsing bugs where multi-value list options are mistakenly accessed as single values
  • Fix inconsistent handling of empty arguments like -blockfilterindex so they are rejected reliably
  • Review #16545 first
  • PR is stacked on unmerged #16545 and includes its commits in the diff
  • Concept approval with review feedback on runtime versus compile-time checks (ajtowns)
  • Concept approval without stated reasons (hebasto, promag)
  • All review suggestions and questions have been addressed or resolved
  • 378 lines added or modified outside tests
  • 767 lines added or modified in tests
  • 176 lines removed in total
  • 14 files, 13 commits
Utilities (logging, arguments, libraries)#18 of 59
P2 · cleanup
  • P2 because it eliminates error-prone getter usage on list arguments and fixes parsing anomalies
  • It establishes argument checking infrastructure that unblocks follow-up config validation work
Reviewability: ReadyStalePaused
Agreement: StrongPositivePositive w/ caveatsNeutralMildDisputedBlockedCrickets
Reviews: current code-review ACKs, then (+stale ACKs) and -NACKs; greener = more ACKs.
Size: lines added or modified outside tests, then in tests; greener = smaller.

Goal

Adds the ALLOW_LIST flag to ArgsManager options and enforces via CheckArgFlags that list options are retrieved with GetArgs() while non-list options are retrieved with GetArg(). It allows combining ALLOW_STRING and ALLOW_INT with ALLOW_BOOL for arguments that take optional values, and converts callers throughout the codebase that improperly invoked single-value methods on list options. It also fixes inconsistent behavior with empty -blockfilterindex="" arguments so they are consistently rejected as errors.

Problem: Calling single-value getters like GetArg() or IsArgSet() on multi-value list arguments is error-prone: GetArg() returns the last command-line value but the first config value in a list, and IsArgSet() can return true on an empty negated list. Additionally, -blockfilterindex="" exhibited position-dependent behavior, enabling all filters in some configurations while triggering parse errors in others.

Evidence of importance:

  • Commit b95db49ce7 explains: 'For example GetArg will return last command line value but first config value in the list, and IsArgSet will return true even if the list is empty if the list was negated.'
  • Commit 7bd8fce664 notes: 'Previous behavior was inconsistent: if -blockfilterindex or -blockfilterindex="" arguments were specified they would normally enable all block filter indexes, but could also trigger "Unknown -blockfilterindex value" errors if followed by later -blockfilterindex arguments.'
  • PR description notes: 'Followup PRs could use the ALLOW_LIST flags for better documentation and error checking in the future. For example, #17493 builds on this to disallow conflicting config values.'

Scope: Stacked on top of unmerged PR #16545; commits up to 0b435cb8fe belong to that base. Includes a scripted-diff commit (d10df8eee1) adding ALLOW_LIST to arguments retrieved with GetArgs.

Risk of a mistake: medium (other). A mistake in argument flag enforcement or parsing could throw a logic_error during startup or misparse valid node configuration parameters.

Changed since the previous assessment: Rebased on updated base PR #16545; the separate rpcauth parsing fix mentioned in the original description was merged separately in #30401.

Reviewability

Ready · Review #16545 first

Stacked on #16545; the base PR's changes are included in this diff.

Waiting on (from the thread read):

  • nothing

Agreement

Strong

substantive support, no open objection (ajtowns)

Thread notes: Converted schema 1 claims by ajtowns from objections to suggestions and added question rc:364559553. Updated ajtowns' stance to support given the Concept ACK and lack of standing objections. / Reclassified ajtowns' claims from objections to suggestions/questions as they do not name costs of merging as-is, added unrecorded question rc:364559553, and updated ajtowns' stance to support.

Objections, suggestions, and questions:

ReviewerTypeHarm, request, or questionStatusMust beAuthor repliedQuote
ajtowns (member)suggestion, approachenforce argument flag checks at compile time rather than runtimeanswered · author explained compile-time checks are easier to add once constraints are in placeansweredyes2020-01-09: 'shame all these checks are happening at runtime rather than compile time though'
Status from: 2020-01-09: ryanofsky: 'Switching enforcement from runtime to compile time after constraints are in already place would be easier by comparison'
ajtowns (member)suggestion, approachsimplify CheckArgFlags to not include ALLOW_ANY types in forbidfixed · fix pushed · author simplified CheckArgFlags in pushansweredyes2020-01-09: 'I don't think it makes sense to ever include any of the `ALLOW_ANY` types in `forbid`'
Status from: 2020-01-24: ryanofsky: 'with suggested checkargflags simplification'
ajtowns (member)suggestion, maintenancerestructure the tests instead of using helper functions that tweak flagsanswered · author declined to restructure tests in this PRansweredyes2020-01-09: 'I think it might be better to restructure the tests than have these special functions that tweak the flags.'
Status from: 2020-01-09: ryanofsky: 'I'm not too inclined to want to restructure the tests, though I'd be happy to review a PR that did.'
ajtowns (member)question, correctnesswhether gArgs.IsArgSet("-rpcauth") should be used insteadanswered · author explained IsArgSet is broken for negated list argumentsansweredyes2020-01-09: '`gArgs.IsArgSet("-rpcauth")` ?'
Status from: 2020-01-09: ryanofsky: 'That would do the wrong thing if the argument is negated.'

Support:

  • hebasto (member) (Concept ACK, 2019-11-24): Concept ACK [not substantive]
  • promag (contributor) (Concept ACK, 2019-12-22): Concept ACK. [not substantive]
  • ajtowns (member) (Concept ACK, 2020-01-09) [read]: Concept ACK, shame all these checks are happening at runtime rather than compile time though

Participants:

  • hebasto (member, support, 1 statements 2019-11-24 to 2019-11-24): Concept ACK
  • promag (contributor, support, 1 statements 2019-12-22 to 2019-12-22): Concept ACK
  • ajtowns (member, support, 4 statements 2020-01-09 to 2020-01-09): Concept ACK; suggested compile-time checks, CheckArgFlags simplification, test restructuring, and asked about IsArgSet
  • fanquake (member, neutral, 1 statements 2023-02-08 to 2023-02-08): moved PR to draft because base PR is a draft

Dependencies

Depends on: #16545

Enables:

Based on (shares commits with): #16545

Base for: #17493, #17581, #17783

Files

849 lines under test/bench/ci.

  • src/test/argsman_tests.cpp +648/-66
  • src/common/args.cpp +157/-31
  • src/common/args.h +162/-18
  • src/init.cpp +45/-36
  • src/test/getarg_tests.cpp +61/-3
  • src/test/fuzz/system.cpp +47/-7
  • src/chainparamsbase.cpp +6/-5
  • src/init/common.cpp +3/-3
  • src/test/logging_tests.cpp +3/-3
  • test/lint/check-doc.py +3/-2
  • src/common/config.cpp +4/-0
  • src/test/util/common.h +4/-0
  • src/wallet/init.cpp +1/-1
  • test/functional/feature_config_args.py +1/-1

Card

The short text the ranking pass compares across PRs.

Adds the ALLOW_LIST flag to ArgsManager and enforces at runtime that multi-value options are accessed via GetArgs() rather than GetArg(). This eliminates internal developer footguns where single-value accessors return inconsistent or unexpected elements from multi-value lists, and resolves position-dependent handling of empty -blockfilterindex arguments. It unblocks follow-up work in #17493 to reject ambiguous duplicate config settings. The PR is stacked on base PR #16545.

Data

dossier JSON · extract JSON · model ledger, generated 2026-11-01T01:16, confidence high, input hash 2f22744aee991c5e
thread read through 2024-12-06 (13 statements), head a79914f0fc
labels: Refactoring · draft

Categories

Utilities (logging, arguments, libraries)

P2 · cleanup

Enforces proper argument fetching patterns across the codebase to prevent error-prone usage of GetArg() on list options and fixes inconsistent parsing for empty options like -blockfilterindex="". It also establishes infrastructure that unblocks follow-up config validation work such as #17493.

Membership: Directly refactors core argument parsing and flag checking in src/common/args.cpp and src/common/args.h.

Factors: security/stability 1, bug 1, performance 0, user value 1, leverage 2