Skip to content

Commit dde07c5

Browse files
authored
Merge pull request #810 from jonsequitur/fixes-for-723
Fixes for 723
2 parents 7725a38 + f5a35f7 commit dde07c5

16 files changed

+239
-130
lines changed

SECURITY.md

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
# Security Policy
2-
3-
## Supported Versions
4-
5-
The .NET Core and ASP.NET Core support policy, including supported versions can be found at the [.NET Core Support Policy Page](https://dotnet.microsoft.com/platform/support/policy/dotnet-core).
6-
7-
## Reporting a Vulnerability
8-
9-
Security issues and bugs should be reported privately to the Microsoft Security Response Center (MSRC), either by emailing [email protected] or via the portal at https://msrc.microsoft.com.
10-
You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your
11-
original message. Further information, including the MSRC PGP key, can be found in the [MSRC Report an Issue FAQ](https://www.microsoft.com/en-us/msrc/faqs-report-an-issue).
12-
13-
Reports via MSRC may qualify for the .NET Core Bug Bounty. Details of the .NET Core Bug Bounty including terms and conditions are at [https://aka.ms/corebounty](https://aka.ms/corebounty).
14-
1+
# Security Policy
2+
3+
## Supported Versions
4+
5+
The .NET Core and ASP.NET Core support policy, including supported versions can be found at the [.NET Core Support Policy Page](https://dotnet.microsoft.com/platform/support/policy/dotnet-core).
6+
7+
## Reporting a Vulnerability
8+
9+
Security issues and bugs should be reported privately to the Microsoft Security Response Center (MSRC), either by emailing [email protected] or via the portal at https://msrc.microsoft.com.
10+
You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your
11+
original message. Further information, including the MSRC PGP key, can be found in the [MSRC Report an Issue FAQ](https://www.microsoft.com/en-us/msrc/faqs-report-an-issue).
12+
13+
Reports via MSRC may qualify for the .NET Core Bug Bounty. Details of the .NET Core Bug Bounty including terms and conditions are at [https://aka.ms/corebounty](https://aka.ms/corebounty).
14+
1515
Please do not open issues for anything you think might have a security implication.

src/System.CommandLine.Rendering.Tests/ViewRenderingTests.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ public void In_Ansi_mode_ConsoleView_keeps_track_of_position_so_that_multiple_Wr
4141
var renderer = new ConsoleRenderer(
4242
_terminal,
4343
OutputMode.Ansi);
44-
4544

4645
var view = new StringsView(new[] {
4746
"1",

src/System.CommandLine.Tests/ArgumentTests.cs

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System.Collections.Generic;
55
using System.CommandLine.Builder;
6+
using System.CommandLine.Help;
67
using System.CommandLine.Invocation;
78
using System.CommandLine.Parsing;
89
using System.IO;
@@ -120,7 +121,7 @@ public void GetDefaultValue_can_return_null()
120121
}
121122

122123
[Fact]
123-
public void Validation_failure_message_can_be_specified()
124+
public void Validation_failure_message_can_be_specified_when_parsing_tokens()
124125
{
125126
var argument = new Argument<FileSystemInfo>(result =>
126127
{
@@ -138,6 +139,46 @@ public void Validation_failure_message_can_be_specified()
138139
.Be("oops!");
139140
}
140141

142+
[Fact]
143+
public void Validation_failure_message_can_be_specified_when_evaluating_default_argument_value()
144+
{
145+
var argument = new Argument<FileSystemInfo>(result =>
146+
{
147+
result.ErrorMessage = "oops!";
148+
return null;
149+
}, true);
150+
151+
argument.Parse("")
152+
.Errors
153+
.Should()
154+
.ContainSingle(e => e.SymbolResult.Symbol == argument)
155+
.Which
156+
.Message
157+
.Should()
158+
.Be("oops!");
159+
}
160+
161+
[Fact]
162+
public void Validation_failure_message_can_be_specified_when_evaluating_default_option_value()
163+
{
164+
var option = new Option<FileSystemInfo>(
165+
"-x",
166+
result =>
167+
{
168+
result.ErrorMessage = "oops!";
169+
return null;
170+
}, true);
171+
172+
option.Parse("")
173+
.Errors
174+
.Should()
175+
.ContainSingle()
176+
.Which
177+
.Message
178+
.Should()
179+
.Be("oops!");
180+
}
181+
141182
[Fact]
142183
public void custom_parsing_of_scalar_value_from_an_argument_with_one_token()
143184
{
@@ -309,6 +350,42 @@ public void Default_value_and_custom_argument_parser_can_be_used_together()
309350
.Should()
310351
.Be(123);
311352
}
353+
354+
[Fact]
355+
public void Multiple_command_arguments_can_have_custom_parse_delegates()
356+
{
357+
var root = new RootCommand
358+
{
359+
new Argument<FileInfo[]>("from", argumentResult =>
360+
{
361+
argumentResult.ErrorMessage = "nope";
362+
return null;
363+
}, true)
364+
{
365+
Arity = new ArgumentArity(0, 2)
366+
},
367+
new Argument<DirectoryInfo>("to", argumentResult =>
368+
{
369+
argumentResult.ErrorMessage = "UH UH";
370+
return null;
371+
}, true)
372+
{
373+
Arity = ArgumentArity.ExactlyOne
374+
}
375+
};
376+
377+
var result = root.Parse("a.txt b.txt /path/to/dir");
378+
379+
result.Errors
380+
.Select(e => e.Message)
381+
.Should()
382+
.Contain("nope");
383+
384+
result.Errors
385+
.Select(e => e.Message)
386+
.Should()
387+
.Contain("UH UH");
388+
}
312389

313390
[Fact]
314391
public void When_custom_conversion_fails_then_an_option_does_not_accept_further_arguments()

src/System.CommandLine.Tests/OptionTests.cs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -325,14 +325,6 @@ public void Option_T_default_value_is_validated()
325325
.Select(e => e.Message)
326326
.Should()
327327
.BeEquivalentTo(new[] { "ERR" });
328-
329-
option
330-
.Parse("")
331-
.Errors
332-
.Select(e => e.Message)
333-
.Should()
334-
.BeEquivalentTo(new[] { "ERR" });
335-
336328
}
337329

338330
protected override Symbol CreateSymbol(string name) => new Option(name);

src/System.CommandLine.Tests/ParseDiagramTests.cs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
33

44
using System.CommandLine.Parsing;
5+
using System.IO;
56
using FluentAssertions;
67
using Xunit;
78

@@ -89,7 +90,6 @@ public void Parse_diagram_identifies_options_where_default_values_have_been_appl
8990
}
9091
};
9192

92-
9393
var result = rootCommand.Parse("-w 9000");
9494

9595
var diagram = result.Diagram();
@@ -114,5 +114,22 @@ public void Parse_diagram_indicates_which_tokens_were_applied_to_which_command_a
114114
.Should()
115115
.Be("[ the-command [ first <one> ] [ second <two> ] [ third <three> <four> <five> ] ]");
116116
}
117+
118+
[Fact]
119+
public void Parse_diagram_indicates_which_tokens_were_applied_to_which_command_argument_for_sequences_of_complex_types()
120+
{
121+
var command = new Command("the-command")
122+
{
123+
new Argument<FileInfo> { Name = "first" },
124+
new Argument<FileInfo> { Name = "second" },
125+
new Argument<FileInfo[]> { Name = "third" }
126+
};
127+
128+
var result = command.Parse("one two three four five");
129+
130+
result.Diagram()
131+
.Should()
132+
.Be("[ the-command [ first <one> ] [ second <two> ] [ third <three> <four> <five> ] ]");
133+
}
117134
}
118135
}

src/System.CommandLine.Tests/ParserTests.MultipleArguments.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ public void Multiple_arguments_of_unspecified_type_are_parsed_correctly()
135135
}
136136
};
137137

138-
var result = root.Parse("src.txt", "dest.txt");
138+
var result = root.Parse("src.txt dest.txt");
139139

140140
result.RootCommandResult
141141
.GetArgumentValueOrDefault("source")
@@ -147,7 +147,6 @@ public void Multiple_arguments_of_unspecified_type_are_parsed_correctly()
147147
.Should()
148148
.Be("dest.txt");
149149
}
150-
151150
}
152151
}
153152
}

src/System.CommandLine.Tests/ParserTests.cs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1371,6 +1371,45 @@ public void When_an_option_with_a_default_value_is_not_matched_then_the_option_r
13711371
.BeTrue();
13721372
}
13731373

1374+
[Fact]
1375+
public void When_an_option_with_a_default_value_is_not_matched_then_there_are_no_tokens()
1376+
{
1377+
var option = new Option<string>(
1378+
"-o",
1379+
() => "the-default");
1380+
1381+
var command = new Command("command")
1382+
{
1383+
option
1384+
};
1385+
1386+
var result = command.Parse("command");
1387+
1388+
result.FindResultFor(option)
1389+
.Token
1390+
.Should()
1391+
.BeNull();
1392+
}
1393+
1394+
[Fact]
1395+
public void When_an_argument_with_a_default_value_is_not_matched_then_there_are_no_tokens()
1396+
{
1397+
var argument = new Argument<string>(
1398+
"o",
1399+
() => "the-default");
1400+
1401+
var command = new Command("command")
1402+
{
1403+
argument
1404+
};
1405+
var result = command.Parse("command");
1406+
1407+
result.FindResultFor(argument)
1408+
.Tokens
1409+
.Should()
1410+
.BeEmpty();
1411+
}
1412+
13741413
[Fact]
13751414
public void Command_default_argument_value_does_not_override_parsed_value()
13761415
{

src/System.CommandLine.Tests/SymbolResultTests.cs

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -27,28 +27,6 @@ public void An_option_with_a_default_value_and_no_explicitly_provided_argument_h
2727
result.Tokens.Should().BeEmpty();
2828
}
2929

30-
[Fact]
31-
public void Default_values_are_reevaluated_and_not_cached_between_parses()
32-
{
33-
var option =
34-
new Option("-x")
35-
{
36-
Argument = new Argument
37-
{
38-
Arity = ArgumentArity.ExactlyOne
39-
}
40-
};
41-
42-
var i = 0;
43-
option.Argument.SetDefaultValueFactory(() => ++i);
44-
45-
var result1 = option.Parse("");
46-
var result2 = option.Parse("");
47-
48-
result1.ValueForOption<int>("x").Should().Be(1);
49-
result2.ValueForOption<int>("x").Should().Be(2);
50-
}
51-
5230
[Fact]
5331
public void HasOption_can_be_used_to_check_the_presence_of_an_option()
5432
{

src/System.CommandLine.Tests/UseHelpTests.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
using System.CommandLine.Invocation;
66
using System.CommandLine.IO;
77
using System.CommandLine.Parsing;
8-
using System.IO;
98
using System.Threading.Tasks;
109
using FluentAssertions;
1110
using Xunit;

src/System.CommandLine/Parsing/ArgumentResult.cs

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ internal ArgumentResult(
2626

2727
internal ParseError CustomError(Argument argument)
2828
{
29+
if (!string.IsNullOrEmpty(ErrorMessage))
30+
{
31+
return new ParseError(ErrorMessage, this);
32+
}
33+
2934
foreach (var symbolValidator in argument.Validators)
3035
{
3136
var errorMessage = symbolValidator(this);
@@ -55,9 +60,25 @@ internal virtual ArgumentConversionResult Convert(
5560

5661
if (parentResult.UseDefaultValueFor(argument))
5762
{
58-
var defaultValueFor = parentResult.GetDefaultValueFor(argument);
59-
60-
return ArgumentConversionResult.Success(argument, defaultValueFor);
63+
if (argument is Argument arg)
64+
{
65+
var argumentResult = new ArgumentResult(arg, Parent);
66+
67+
var defaultValue = arg.GetDefaultValue(argumentResult);
68+
69+
if (string.IsNullOrEmpty(argumentResult.ErrorMessage))
70+
{
71+
return ArgumentConversionResult.Success(
72+
argument,
73+
defaultValue);
74+
}
75+
else
76+
{
77+
return ArgumentConversionResult.Failure(
78+
argument,
79+
argumentResult.ErrorMessage);
80+
}
81+
}
6182
}
6283

6384
if (argument is Argument a &&
@@ -107,8 +128,5 @@ bool ShouldCheckArity()
107128
optionResult.IsImplicit);
108129
}
109130
}
110-
111-
internal override object CreateDefaultArgumentResultAndGetItsValue(Argument argument) =>
112-
argument.GetDefaultValue(this);
113131
}
114132
}

0 commit comments

Comments
 (0)