commandlineparser / commandlineparser/commandline

Parameter name is treated as parameter value

オープン
#857 コメント 4 件 リアクション 1 件 担当者 0 名 GitHub で見る
bug help wanted
主要言語
C#
スター
4.8k
フォーク
478
PR マージ指標
30日以内にマージされた PR はありません

説明

If I omit parameter value for one parameter name, next parametername is treated as value of the parameter.
Occurred at v2.9.1 from Nuget.

### What I observed
Code:
```
using System;
using CommandLine;

class Options
{
[Option('a', "option1", Required = true)]
public string Option1 { get; set; }

[Option('b', "option2", Required = false)]
public int option2 { get; set; }
}

class Program
{
static int Main(string[] args)
{
return Parser.Default.ParseArguments(args)
.MapResult(
options => RunAndReturnExitCode(options),
_ => -1);
}

static int RunAndReturnExitCode(Options options)
{
Console.WriteLine($"option1={options.Option1}, option2={options.option2}");
return 0;
}
}
```
Command line,
`$command --option1 --option2 5`
gives the result output,
`option1=option2, option2=0`

But expected result is to report error with lacking of required "option1".

### Suggested fix
In the method "CommandLine.Core.TokenPartitioner.PartitionTokensByType", scalarTokens.add(Scalar nem token) shall be occurred only when the following value is confirmed.

```
public static Tuple, IEnumerable, IEnumerable, IEnumerable> PartitionTokensByType(
IEnumerable tokens,
Func> typeLookup)
{
var switchTokens = new List();
var scalarTokens = new List();
var sequenceTokens = new List();
var nonOptionTokens = new List();
var sequences = new Dictionary>();
var count = new Dictionary();
var max = new Dictionary>();
var state = SequenceState.TokenSearch;
var separatorSeen = false;
Token nameToken = null;
foreach (var token in tokens)
{
if (token.IsValueForced())
{
separatorSeen = false;
nonOptionTokens.Add(token);
}
else if (token.IsName())
{
separatorSeen = false;
if (typeLookup(token.Text).MatchJust(out var info))
{
switch (info.TargetType)
{
case TargetType.Switch:
nameToken = null;
switchTokens.Add(token);
state = SequenceState.TokenSearch;
break;
case TargetType.Scalar:
nameToken = token;
// scalarTokens.Add(nameToken); <- don't add here
state = SequenceState.ScalarTokenFound;
break;
case TargetType.Sequence:
nameToken = token;
if (! sequences.ContainsKey(nameToken))
{
sequences[nameToken] = new List();
count[nameToken] = 0;
max[nameToken] = info.MaxItems;
}
state = SequenceState.SequenceTokenFound;
break;
}
}
else
{
nameToken = null;
nonOptionTokens.Add(token);
state = SequenceState.TokenSearch;
}
}
else
{
switch (state)
{
case SequenceState.TokenSearch:
case SequenceState.ScalarTokenFound when nameToken == null:
case SequenceState.SequenceTokenFound when nameToken == null:
separatorSeen = false;
nameToken = null;
nonOptionTokens.Add(token);
state = SequenceState.TokenSearch;
break;

case SequenceState.ScalarTokenFound:
separatorSeen = false;
scalarTokens.Add(nameToken); // add here instead so that scalar name token is valid only when a value is given
nameToken = null;
scalarTokens.Add(token);
state = SequenceState.TokenSearch;
break;

......
```

コントリビューションガイド

このリポジトリのコントリビューションガイドは索引されていません

調査の方向性

CommandLine.Core.TokenPartitioner.PartitionTokensByType から開始し、提供された C# の例を使用して `--option1 --option2 5` で問題を再現します。ScalarTokenFound の状態を追跡し、スカラーオプション名が値に続かれている場合にのみ保持されることを確認します。option2 をその値として扱うのではなく、欠落している必須オプション option1 がエラーとして報告されれば完了です。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
csharp
領域
cli
issue の種類
バグ
難易度
3/5
見積もり時間
1〜2日
活発さ
停滞
明瞭さ
明確に書かれている
初心者へのやさしさ
35/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。