options: reject an empty long option name
An argument of the form "--=VALUE" leaves an empty option name, which startswith() treats as a prefix of every defined option. Depending on how many long options a namespace defines that yields either an ambiguity error listing every option, or, with exactly one option defined, a unique partial match that silently parses "--=VALUE" as that option.
This commit is contained in:
committed by
Yu Watanabe
parent
3ae53ab8f6
commit
5dc41f8283
@@ -223,6 +223,16 @@ int option_parse(
|
||||
/* argument (if any) is separate */
|
||||
optname = state->argv[state->optind];
|
||||
|
||||
/* An empty name, i.e. "--=…", would be a prefix of every option, so reject it
|
||||
* right away rather than let it match. */
|
||||
if (isempty(optname + 2)) {
|
||||
r = log_full_errno(LOG_ERR + state->log_level_shift,
|
||||
SYNTHETIC_ERRNO(EINVAL),
|
||||
"%s: unrecognized option '%s'",
|
||||
program_invocation_short_name, optname);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
const Option *last_partial = NULL;
|
||||
unsigned n_partial_matches = 0; /* The commandline option matches a defined prefix. */
|
||||
|
||||
|
||||
@@ -1580,4 +1580,24 @@ TEST(option_get_synopsis) {
|
||||
test_option_get_synopsis_one(&(const Option) { 0, OPTION_POSITIONAL_ENTRY, 'u', "(fixed)", "unused" }, "/", true, "(fixed)");
|
||||
}
|
||||
|
||||
TEST(option_empty_long_name) {
|
||||
static const Option one_option[] = {
|
||||
{ 1, .short_code = 'o', .long_code = "output", .metavar = "ARG" },
|
||||
{}
|
||||
};
|
||||
|
||||
static const Option two_options[] = {
|
||||
{ 1, .short_code = 'o', .long_code = "output", .metavar = "ARG" },
|
||||
{ 2, .long_code = "help" },
|
||||
{}
|
||||
};
|
||||
|
||||
/* "--=…" carries an empty long option name, which must not prefix-match every defined option.
|
||||
* With a single option defined that would otherwise look like a unique partial match. */
|
||||
test_option_invalid_one(STRV_MAKE("arg0", "--=foo"), one_option);
|
||||
test_option_invalid_one(STRV_MAKE("arg0", "--="), one_option);
|
||||
test_option_invalid_one(STRV_MAKE("arg0", "--=foo"), two_options);
|
||||
test_option_invalid_one(STRV_MAKE("arg0", "--="), two_options);
|
||||
}
|
||||
|
||||
DEFINE_TEST_MAIN(LOG_DEBUG);
|
||||
|
||||
Reference in New Issue
Block a user