#16545 refactor: Implement missing error checking for ArgsManager flags
| Reviewability | Reviews | Agreement | Size | ||||
|---|---|---|---|---|---|---|---|
| #16545 refactor: Implement missing error checking for ArgsManager flags | Ready | 0 (+1) -1 | Mild | 308 + 542 tests | |||
|
|
|
|
| |||
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
Implements parsing and startup validation for `ALLOW_BOOL`, `ALLOW_INT`, `ALLOW_STRING`, and `ALLOW_LIST` argument flags in `ArgsManager`. It rejects malformed typed inputs (such as double negations or duplicate config keys for non-list arguments) during configuration parsing and enforces flag consistency across `GetArg` accessors at runtime. Existing production arguments remain on `ALLOW_ANY`, leaving current node behavior unchanged until options adopt the new flags.
Problem: Command-line arguments and configuration settings historically underwent minimal type validation during parsing, resulting in type-coercion footguns (such as `-nofoo` returning the string `"0"`, which previously caused `-nowallet` to create a wallet file named `"0"`). Additionally, duplicate non-list assignments in configuration files are silently ignored, and developers can invoke mismatched accessors (such as `GetIntArg` on a non-integer argument) without error enforcement.
Evidence of importance:
- Commit 99c35134de notes historical footguns: "negated settings will return '' empty strings instead of '0' strings (in the past the '0' strings caused strangeness like '-nowallet' options creating wallet files named '0')"
- Commit 97071b909f states: "if a non-list setting is assigned multiple times in the same section of a configuration file, the later assignments trigger errors instead of being silently ignored"
Risk of a mistake: medium (other, tests). A mistake in configuration parsing or argument flag validation could prevent nodes from starting or throw unhandled logic errors on valid CLI/config settings.
Changed since the previous assessment: Added test coverage for settings.json parsing with type flags, updated fuzz harness exception handling for stricter type checks, and applied documentation and grammar cleanups.
Reviewability
Ready
Nothing known that would invalidate a review now.
Waiting on (from the thread read):
- reviewer: review of the latest rebases and updates 2024-12-09
Agreement
Mild
objection that needs a change was answered, no reply from the objector (ajtowns (NACK): interpreting empty setting values as resetting to defaults alters existing configuration semantics)
Thread notes: The author updated and rebased the PR through multiple iterations fixing conflicts and CI issues.
Objections, suggestions, and questions:
| Reviewer | Type | Harm, request, or question | Status | Must be | Author replied | Quote |
|---|---|---|---|---|---|---|
| promag (contributor) | suggestion, correctness | use an assertion instead of throwing a logic_error | accepted · author explained logic_error is needed for testing and clear error messages; promag agreed | answered | yes | 2019-08-06: 'Looks like this should be an assertion?' Status from: 2019-08-07: promag: 'Actually I did check and ran the tests with my change and I understand the idea of testing the exception, which wouldn't' |
| hebasto (member) | suggestion, style | Specify the underlying type for the Flags enum as unsigned int | fixed · fix pushed · author specified the underlying type | changed | yes | 2019-08-10: 'Could the underlying type be specified?' Status from: 2019-08-14: ryanofsky: 'Done in 9a1e20eef36b9dfff9de7780b0edd30b8ae92487' |
| ajtowns (member) | objection, interface | interpreting empty setting values as resetting to defaults alters existing configuration semantics | answered · author explained empty setting reset is deliberate and does not affect existing options; ajtowns did not follow up | changed | yes | 2020-01-28: 'making `-value=` reset things to defaults changes the meaning of existing configs, and while that might be fine if it were a new system, it doesn't seem useful enough to justify introducing an incompa' Status from: 2020-09-01: ryanofsky: 'Making the change you suggest would require either choosing a new SettingsValue representation or making it impossible t' |
| fanquake (member) | suggestion, style | Use std::optional in new code | fixed · fix pushed · updated to use std::optional | changed | no | 2021-03-15: 'Please use `std::optional` in new code.' Status from: 2024-08-05: ryanofsky: 'with suggested doxygen fixes and other tweaks' |
| maflcko (member) | objection, approach | allowing multi-flag combinations creates footguns and subtle behavioral inconsistencies across existing options | fixed · fix pushed · author dropped support for flag combinations in PR push | changed | yes | 2024-08-05: 'Merging this as-is and unlocking the footgun just seems too risky to me. This is why I asked to make this an enum class for now, disallowing combinations, so that they can be reviewed and added later ' Status from: 2024-08-23: ryanofsky: 'dropping support for flag combinations and fixing a commit message as suggested' |
| hodlinator (member) | suggestion, approach | Update the outdated ALLOW_INT | ALLOW_BOOL example in wallet.cpp to avoid requiring a different integer default | answered · author removed the outdated example and referenced new tests | answered | yes | 2024-08-15: 'The example for `ALLOW_INT | ALLOW_BOOL` in 6865a198f5db30bd494b3a2540f47ee728963908 is a bit worrying.' Status from: 2024-08-23: ryanofsky: 'Thanks, and yes that example is very out of date. I removed it from the PR description.' |
| l0rinc (member) | objection, correctness | catching broad exceptions in system fuzz test can give false confidence by masking unexpected errors | fixed · fix pushed · author added specific exception checks in fuzz test | answered | yes | 2024-09-25: 'doesn't this defeat the purpose and give us false confidence? Can we at least assert something in the message to make sure it's not an unrelated exception?' Status from: 2024-12-09: ryanofsky: 'Yes, added checks. I don't think most existing fuzz tests are so strict about what exceptions are thrown' |
Support:
- promag (contributor) (2019-08-07) [both]: Looks good, read the code and tried locally [not substantive]
- hebasto (member) (Concept ACK, 2019-08-10): supports adding error checking for ArgsManager flags [not substantive]
- laanwj (member) (Concept ACK, 2019-10-23): consistent argument error checking is good
- hebasto (member) (ACK, 2020-01-06) [tested]: tested on Linux Mint 19.3
- hebasto (member) (ACK, 2020-01-07) [tested]: re-ACK tested on Linux Mint 19.3
- hebasto (member) (ACK, 2020-01-07): just fix a typo [not substantive]
- hodlinator (member) (Concept ACK, 2024-08-15) [read]: incremental approach of this PR + gradually activating it for existing args will achieve a better baseline to approach future compile-time initiatives from
- l0rinc (member) (Approach ACK, 2024-09-25) [read]: did a first scan over the implementation and left nits and refactoring ideas [not substantive]
Participants:
- hebasto (member, support, 13 statements 2019-08-04 to 2020-01-07): Concept ACK and repeated ACKs after testing on Linux Mint
- promag (contributor, support, 11 statements 2019-08-06 to 2020-01-09): read code and tested locally, suggested assertion and usage examples
- laanwj (member, support, 1 statements 2019-10-23 to 2019-10-23): Concept ACK for consistent argument error checking
- ajtowns (member, objection, 13 statements 2020-01-09 to 2021-09-01): objected to resetting empty values to defaults altering existing config semantics
- fanquake (member, neutral, 1 statements 2021-03-15 to 2021-03-15): requested using std::optional in new code
- maflcko (member, objection, 7 statements 2021-08-19 to 2024-09-23): objected to combining flags without starting from single types like bool
- achow101 (member, neutral, 1 statements 2023-09-23 to 2023-09-23): commented during omitted discussion period
- hodlinator (member, support, 30 statements 2024-07-23 to 2024-10-02): Concept ACK praising incremental argument typing, tested CLI flags thoroughly
- l0rinc (member, support, 28 statements 2024-08-09 to 2024-10-02): Approach ACK, proposed code structure refactorings and tightening fuzz exceptions
Dependencies
Files
564 lines under test/bench/ci.
- src/test/argsman_tests.cpp +425/-9
- src/common/args.cpp +160/-31
- src/common/args.h +144/-16
- src/test/getarg_tests.cpp +61/-3
- src/test/fuzz/system.cpp +48/-7
- test/lint/check-doc.py +3/-2
- src/common/config.cpp +4/-0
- src/test/util/common.h +4/-0
- test/functional/feature_config_args.py +1/-1
Card
The short text the ranking pass compares across PRs.
Implements runtime parsing and startup validation for ALLOW_BOOL, ALLOW_INT, ALLOW_STRING, and ALLOW_LIST argument flags in ArgsManager. Currently, configuration settings lack strict type validation, causing type-coercion footguns like negated options resolving to string "0" (which previously caused -nowallet to create a wallet named "0") and duplicate configuration file assignments being silently ignored. This change rejects malformed typed inputs at startup and raises internal errors on mismatched getter calls, while keeping existing arguments under ALLOW_ANY until migrated. It serves as the prerequisite foundation for several follow-up PRs adding compile-time and runtime option checking (#17580, #17783, #22978).
Data
thread read through 2024-12-09 (191 statements), head 0b435cb8fe
labels: Utils/log/libs · draft
Categories
Utilities (logging, arguments, libraries)
P2 · unblocks #17580
Implements argument flag type validation to eliminate configuration footguns and unblocks subsequent PRs transitioning options to typed flags. Commit 99c35134de highlights historical footguns where '-nowallet' created a wallet file named '0', and commit 97071b909f prevents duplicate non-list configuration settings from being silently ignored, laying foundational safety for argument parsing across the node.
Membership: Carries the Utils/log/libs label and directly modifies ArgsManager in src/common/args.cpp and src/common/args.h.
Factors: security/stability 1, bug 1, performance 0, user value 1, leverage 2