@@ -24,11 +24,13 @@ public class ModelStateDictionary : IReadOnlyDictionary<string, ModelStateEntry>
24
24
/// </summary>
25
25
public static readonly int DefaultMaxAllowedErrors = 200 ;
26
26
27
+ private const int DefaultMaxRecursionDepth = 32 ;
27
28
private const char DelimiterDot = '.' ;
28
29
private const char DelimiterOpen = '[' ;
29
30
30
31
private readonly ModelStateNode _root ;
31
32
private int _maxAllowedErrors ;
33
+ private int _maxRecursionDepth ;
32
34
33
35
/// <summary>
34
36
/// Initializes a new instance of the <see cref="ModelStateDictionary"/> class.
@@ -44,6 +46,7 @@ public ModelStateDictionary()
44
46
public ModelStateDictionary ( int maxAllowedErrors )
45
47
{
46
48
MaxAllowedErrors = maxAllowedErrors ;
49
+ MaxRecursionDepth = DefaultMaxRecursionDepth ;
47
50
var emptySegment = new StringSegment ( buffer : string . Empty ) ;
48
51
_root = new ModelStateNode ( subKey : emptySegment )
49
52
{
@@ -153,7 +156,7 @@ public bool IsValid
153
156
}
154
157
155
158
/// <inheritdoc />
156
- public ModelValidationState ValidationState => GetValidity ( _root ) ?? ModelValidationState . Valid ;
159
+ public ModelValidationState ValidationState => GetValidity ( _root , currentDepth : 0 ) ?? ModelValidationState . Valid ;
157
160
158
161
/// <inheritdoc />
159
162
public ModelStateEntry this [ string key ]
@@ -173,6 +176,22 @@ public ModelStateEntry this[string key]
173
176
// Flag that indicates if TooManyModelErrorException has already been added to this dictionary.
174
177
private bool HasRecordedMaxModelError { get ; set ; }
175
178
179
+ internal int MaxRecursionDepth
180
+ {
181
+ get
182
+ {
183
+ return _maxRecursionDepth ;
184
+ }
185
+ set
186
+ {
187
+ if ( value < 0 )
188
+ {
189
+ throw new ArgumentOutOfRangeException ( nameof ( value ) ) ;
190
+ }
191
+ _maxRecursionDepth = value ;
192
+ }
193
+ }
194
+
176
195
/// <summary>
177
196
/// Adds the specified <paramref name="exception"/> to the <see cref="ModelStateEntry.Errors"/> instance
178
197
/// that is associated with the specified <paramref name="key"/>. If the maximum number of allowed
@@ -409,7 +428,7 @@ public ModelValidationState GetFieldValidationState(string key)
409
428
}
410
429
411
430
var item = GetNode ( key ) ;
412
- return GetValidity ( item ) ?? ModelValidationState . Unvalidated ;
431
+ return GetValidity ( item , currentDepth : 0 ) ?? ModelValidationState . Unvalidated ;
413
432
}
414
433
415
434
/// <summary>
@@ -661,9 +680,9 @@ private static StringSegment FindNext(string key, ref MatchResult currentMatch)
661
680
return new StringSegment ( key , keyStart , index - keyStart ) ;
662
681
}
663
682
664
- private static ModelValidationState ? GetValidity ( ModelStateNode node )
683
+ private static ModelValidationState ? GetValidity ( ModelStateNode node , int currentDepth )
665
684
{
666
- if ( node == null )
685
+ if ( node == null || currentDepth >= MaxRecursionDepth )
667
686
{
668
687
return null ;
669
688
}
@@ -686,9 +705,11 @@ private static StringSegment FindNext(string key, ref MatchResult currentMatch)
686
705
687
706
if ( node . ChildNodes != null )
688
707
{
708
+ currentDepth ++ ;
709
+
689
710
for ( var i = 0 ; i < node . ChildNodes . Count ; i ++ )
690
711
{
691
- var entryState = GetValidity ( node . ChildNodes [ i ] ) ;
712
+ var entryState = GetValidity ( node . ChildNodes [ i ] , currentDepth ) ;
692
713
693
714
if ( entryState == ModelValidationState . Unvalidated )
694
715
{
0 commit comments