Skip to content

Commit aefbf35

Browse files
michaelgwelchjonsequitur
authored andcommitted
Reduce maximum possible arity of an arg to 100,000
To fix #997 (overflow exception when calculating remainging capcity of arguments) this places an arbitray cap on the maximum arity of an argument. In this commit this was set to 100,000. This is enforced in the constructor, and by removing the setters on MinimumNumberOfValues and MaximumNumberOfValues.
1 parent ecb3bd1 commit aefbf35

File tree

5 files changed

+62
-20
lines changed

5 files changed

+62
-20
lines changed

src/System.CommandLine.DragonFruit.Tests/ConfigureFromMethodTests.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,11 @@ public async Task Single_character_parameters_generate_aliases_that_accept_a_sin
7373
[InlineData(nameof(Method_having_string_argument), 1, 1)]
7474
[InlineData(nameof(Method_having_string_argument_with_null_default_value), 0, 1)]
7575
[InlineData(nameof(Method_having_string_argument_with_non_null_default_value), 0, 1)]
76-
[InlineData(nameof(Method_having_string_array_arguments), 0, int.MaxValue)]
77-
[InlineData(nameof(Method_having_string_array_arguments_with_default_value), 0, int.MaxValue)]
76+
[InlineData(nameof(Method_having_string_array_arguments), 0, ArgumentArity.MaximumArity)]
77+
[InlineData(nameof(Method_having_string_array_arguments_with_default_value), 0, ArgumentArity.MaximumArity)]
7878
[InlineData(nameof(Method_having_FileInfo_argument), 1, 1)]
7979
[InlineData(nameof(Method_having_FileInfo_argument_with_default_value), 0, 1)]
80-
[InlineData(nameof(Method_having_FileInfo_array_args), 0, int.MaxValue)]
80+
[InlineData(nameof(Method_having_FileInfo_array_args), 0, ArgumentArity.MaximumArity)]
8181
public void Parameters_named_arguments_generate_command_arguments_having_the_correct_arity(
8282
string methodName,
8383
int minNumberOfValues,

src/System.CommandLine.Tests/Binding/TypeConversionTests.cs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -723,26 +723,26 @@ public void Values_can_be_correctly_converted_to_array_of_int_without_the_parser
723723
}
724724

725725
[Theory]
726-
[InlineData(0, int.MaxValue, typeof(string[]))]
726+
[InlineData(0, ArgumentArity.MaximumArity, typeof(string[]))]
727727
[InlineData(0, 3, typeof(string[]))]
728-
[InlineData(0, int.MaxValue, typeof(IEnumerable<string>))]
728+
[InlineData(0, ArgumentArity.MaximumArity, typeof(IEnumerable<string>))]
729729
[InlineData(0, 3, typeof(IEnumerable<string>))]
730-
[InlineData(0, int.MaxValue, typeof(List<string>))]
730+
[InlineData(0, ArgumentArity.MaximumArity, typeof(List<string>))]
731731
[InlineData(0, 3, typeof(List<string>))]
732-
[InlineData(0, int.MaxValue, typeof(IList<string>))]
732+
[InlineData(0, ArgumentArity.MaximumArity, typeof(IList<string>))]
733733
[InlineData(0, 3, typeof(IList<string>))]
734-
[InlineData(0, int.MaxValue, typeof(ICollection<string>))]
734+
[InlineData(0, ArgumentArity.MaximumArity, typeof(ICollection<string>))]
735735
[InlineData(0, 3, typeof(ICollection<string>))]
736736

737-
[InlineData(1, int.MaxValue, typeof(string[]))]
737+
[InlineData(1, ArgumentArity.MaximumArity, typeof(string[]))]
738738
[InlineData(1, 3, typeof(string[]))]
739-
[InlineData(1, int.MaxValue, typeof(IEnumerable<string>))]
739+
[InlineData(1, ArgumentArity.MaximumArity, typeof(IEnumerable<string>))]
740740
[InlineData(1, 3, typeof(IEnumerable<string>))]
741-
[InlineData(1, int.MaxValue, typeof(List<string>))]
741+
[InlineData(1, ArgumentArity.MaximumArity, typeof(List<string>))]
742742
[InlineData(1, 3, typeof(List<string>))]
743-
[InlineData(1, int.MaxValue, typeof(IList<string>))]
743+
[InlineData(1, ArgumentArity.MaximumArity, typeof(IList<string>))]
744744
[InlineData(1, 3, typeof(IList<string>))]
745-
[InlineData(1, int.MaxValue, typeof(ICollection<string>))]
745+
[InlineData(1, ArgumentArity.MaximumArity, typeof(ICollection<string>))]
746746
[InlineData(1, 3, typeof(ICollection<string>))]
747747
public void Max_arity_greater_than_1_converts_to_enumerable_types(
748748
int minArity,

src/System.CommandLine.Tests/ParserTests.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1994,6 +1994,38 @@ public void Tokens_are_not_split_if_the_part_before_the_delimiter_is_not_an_opti
19941994
"jdbc:sqlserver://10.0.0.2;databaseName=main");
19951995
}
19961996

1997+
[Fact]
1998+
public void A_subcommand_wont_overflow_when_checking_maximum_argument_capcity()
1999+
{
2000+
// Tests bug identified in https://github.com/dotnet/command-line-api/issues/997
2001+
2002+
var argument1 = new Argument("arg1")
2003+
{
2004+
Arity = ArgumentArity.ExactlyOne
2005+
};
2006+
2007+
var argument2 = new Argument<string[]>("arg2")
2008+
{
2009+
Arity = ArgumentArity.OneOrMore
2010+
};
2011+
2012+
var command = new Command("subcommand")
2013+
{
2014+
argument1,
2015+
argument2
2016+
};
2017+
2018+
var rootCommand = new RootCommand()
2019+
{
2020+
command
2021+
};
2022+
2023+
var parseResult = rootCommand.Parse("subcommand arg1 arg2");
2024+
2025+
Action act = () => parseResult.GetSuggestions();
2026+
act.Should().NotThrow();
2027+
}
2028+
19972029
[TypeConverter(typeof(CustomTypeConverter))]
19982030
public class ClassWithCustomTypeConverter
19992031
{

src/System.CommandLine/ArgumentArity.cs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ namespace System.CommandLine
99
{
1010
public class ArgumentArity : IArgumentArity
1111
{
12+
public const int MaximumArity = 100_000;
13+
1214
public ArgumentArity(int minimumNumberOfValues, int maximumNumberOfValues)
1315
{
1416
if (minimumNumberOfValues < 0)
@@ -21,13 +23,18 @@ public ArgumentArity(int minimumNumberOfValues, int maximumNumberOfValues)
2123
throw new ArgumentException($"{nameof(maximumNumberOfValues)} must be greater than or equal to {nameof(minimumNumberOfValues)}");
2224
}
2325

26+
if (maximumNumberOfValues > MaximumArity)
27+
{
28+
throw new ArgumentException($"{nameof(maximumNumberOfValues)} must be less than or equal to {nameof(MaximumArity)}");
29+
}
30+
2431
MinimumNumberOfValues = minimumNumberOfValues;
2532
MaximumNumberOfValues = maximumNumberOfValues;
2633
}
2734

28-
public int MinimumNumberOfValues { get; set; }
35+
public int MinimumNumberOfValues { get; }
2936

30-
public int MaximumNumberOfValues { get; set; }
37+
public int MaximumNumberOfValues { get; }
3138

3239
internal static FailedArgumentConversionArityResult? Validate(
3340
SymbolResult symbolResult,
@@ -71,9 +78,9 @@ public ArgumentArity(int minimumNumberOfValues, int maximumNumberOfValues)
7178

7279
public static IArgumentArity ExactlyOne => new ArgumentArity(1, 1);
7380

74-
public static IArgumentArity ZeroOrMore => new ArgumentArity(0, int.MaxValue);
81+
public static IArgumentArity ZeroOrMore => new ArgumentArity(0, MaximumArity);
7582

76-
public static IArgumentArity OneOrMore => new ArgumentArity(1, int.MaxValue);
83+
public static IArgumentArity OneOrMore => new ArgumentArity(1, MaximumArity);
7784

7885
internal static IArgumentArity Default(Type type, Argument argument, ISymbol parent)
7986
{

src/System.CommandLine/Parsing/SymbolResult.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,12 @@ private protected SymbolResult(
4444
private protected virtual int RemainingArgumentCapacity =>
4545
MaximumArgumentCapacity() - Tokens.Count;
4646

47-
internal int MaximumArgumentCapacity() =>
48-
Symbol.Arguments()
49-
.Sum(a => a.Arity.MaximumNumberOfValues);
47+
internal int MaximumArgumentCapacity()
48+
{
49+
var maximumArgumentCapacity = Symbol.Arguments()
50+
.Sum(a => a.Arity.MaximumNumberOfValues);
51+
return (int) Math.Min(maximumArgumentCapacity, int.MaxValue);
52+
}
5053

5154
protected internal ValidationMessages ValidationMessages
5255
{

0 commit comments

Comments
 (0)