Reject an empty option name in getMatchingOptions#434
Open
farkhalit wants to merge 1 commit into
Open
Conversation
An empty name after hyphen stripping matched every long option, so the token "--=value" bound the value to a long option that was never named.
There was a problem hiding this comment.
Pull request overview
This PR fixes a parsing edge case where an “empty” long option name (e.g., --=value) could incorrectly match and bind to any defined long option due to partial-matching behavior in Options#getMatchingOptions.
Changes:
- Add an early-return in
Options#getMatchingOptionsso an empty cleaned option name yields no matches. - Add unit coverage ensuring empty/
-/--inputs don’t match, and--=/etc/shadowis rejected by bothDefaultParserandPosixParser.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| src/main/java/org/apache/commons/cli/Options.java | Prevents empty cleaned option names from matching all long options in partial-match lookup. |
| src/test/java/org/apache/commons/cli/OptionsTest.java | Adds regression tests for empty-name matching and --=value rejection across parsers. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+222
to
+225
| // an empty name is not a partial name, it would match every long option | ||
| if (Util.isEmpty(clean)) { | ||
| return matchingOpts; | ||
| } |
garydgregory
requested changes
Jul 23, 2026
garydgregory
left a comment
Member
There was a problem hiding this comment.
@farkhalit
Please review the copilot comment and update the comment and/or the implementation.
TY!
Member
|
@farkhalit ping 🔔 |
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 free
to 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.
Repro:
--=/etc/shadowparsed against anOptionsthat holds a single long option--config-file. BothDefaultParserandPosixParserreturn aCommandLinewithconfig-fileset to/etc/shadow, and an empty argument list. Nothing on the command line named that option.Cause:
getMatchingOptionsstrips the hyphens off--, leaving an empty name, andlongOpt.startsWith("")holds for every entry, so an empty name matches the entire long option table.handleLongOptionWithEqualsplits--=Vinto opt--and valueV, sees one match, and binds.PosixParser.flattenreaches the same list from its own--branch. With more than one long option defined the same token raisesAmbiguousOptionExceptionnaming all of them rather than rejecting it, andisLongOptionclassifies-=as an option, so-=cannot be passed as a value to the option before it.Fix: an empty name is not a partial name, so return no matches for it. Both parsers share that one lookup, and
--=Vnow reacheshandleUnknownTokenlike any other token that names no option.What this costs an application is the assumption that a long option is only set when its name appears in argv. A launcher or wrapper that inspects argv and refuses, say,
--config-filesees--=...name nothing, while the parser behind it binds the value anyway.mvn; that'smvnon the command line by itself.