Uh oh!
There was an error while loading. Please reload this page.
Remove the never-populated globalArgumentMap from SubCommandArgumentParser - #786
Merged
vharseko merged 1 commit intoJul 29, 2026
Conversation
…arser SubCommandArgumentParser declared a globalArgumentMap that was read in two places but never written to, so both reads were dead. Checking the history, the map was born that way in the OPENDJ-1303 commit that split opendj-cli out into its own module; no commit ever added a put. Both reads duplicate checks that already work against globalLongIDMap: * SubCommand.addArgument() called hasGlobalArgument() and then, 26 lines further down, getGlobalArgumentForLongID() for the same condition. The second check is the stricter one, since by then the identifier has been normalised, so it also catches conflicts that differ only by case. The dead first check is removed. * addGlobalArgument() rejected duplicate global names via the empty map, while the live check against globalLongIDMap sat inside the "if (!longArgumentsCaseSensitive())" branch. The dead check is removed and the live one hoisted out of that branch, so duplicate global long identifiers are now also rejected for a case sensitive parser. hasGlobalArgument() is kept, since it is public, and now resolves against globalLongIDMap through the existing formatLongIdentifier() helper. The hoisted check is the only behaviour change. It cannot affect the eight tools that use this parser - dsconfig, dsreplication, status, uninstall, backendstat, manage-account, upgrade and base64 - because they all construct the parser with longArgumentsCaseSensitive = false, so the check already ran for them. Each was run with --help, and dsconfig also per subcommand, without any ArgumentException. Adds regression tests for both reads; the two that cover the fixed behaviour fail against the previous code.
maximthomas
approved these changes
Jul 29, 2026
Uh oh!
There was an error while loading. Please reload this page.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Clears
java/empty-containeralert #686 — "The contents of this container are never initialized".Problem
SubCommandArgumentParserdeclareswhich is read in two places but never written to.
git log -S "globalArgumentMap.put"returns nothing: the map was born empty in the OPENDJ-1303 commit that splitopendj-cliout into its own module, and no commit has ever added aput. Both reads are therefore dead code.Both reads duplicate a check that already works
The important finding is that neither read guards anything that is not already guarded by
globalLongIDMap, which is populated.SubCommand.addArgument()checked the same condition twice, 26 lines apart:The live check at line 255 is the stricter of the two: by that point
longIDhas been normalised, so it also catches conflicts that differ only by case. The dead check is removed.addGlobalArgument()rejected duplicate global names through the empty map, while the live equivalent againstglobalLongIDMapsat inside theif (!longArgumentsCaseSensitive())branch. The dead check is removed and the live one hoisted out of that branch.hasGlobalArgument()is public, so it is kept rather than deleted, and now resolves againstglobalLongIDMapthrough the existingArgumentParser.formatLongIdentifier()helper — the same normalisation used when writing to that map.Risk
The hoisted duplicate check is the only behaviour change: a case-sensitive parser now rejects two global arguments sharing a long identifier, which it previously accepted silently.
That cannot affect any shipped tool. All eight users of this parser construct it with
longArgumentsCaseSensitive = false, so the check already ran for them:dsconfigfalsedsreplication,status,uninstall(viaSecureConnectionCliParser)falsebackendstat,manage-account,upgradefalsebase64falseThis was confirmed by running each tool against the patched build — no
ArgumentExceptionanywhere:dsconfig --help(all subcommand groups),dsconfig list-backends --help,dsconfig set-global-configuration-prop --helpdsreplication --help,status --help,uninstall --helpbackendstat --help,manage-account --help,upgrade --helpbase64 --help,base64 encode --helpTesting
mvn -pl opendj-cli test— 46 tests run, 0 failures (43 before).Three tests were added to
TestSubCommandArgumentParserTestCase, which already exercises a case-sensitive parser:testHasGlobalArgument— a registered global argument is now discoverable by long identifier, with the parser's case-sensitivity respected.testDuplicateGlobalArgumentIsRejected— duplicate global long identifiers are rejected for both case-sensitive and case-insensitive parsers.testSubCommandArgumentConflictingWithGlobalIsRejected— a sub-command argument may not shadow a global one.The first two were run against the unpatched production code to confirm they actually pin the fix, and both fail there:
The third passes before and after — it is a characterisation test pinning the live check at line 255 that the removed duplicate relied on.
Note
ERR_ARG_SUBCOMMAND_ARGUMENT_GLOBAL_CONFLICTandERR_SUBCMDPARSER_DUPLICATE_GLOBAL_ARG_NAMEare now unused incli.properties. They were left in place so that message ordinals are not disturbed.