@@ -19,15 +19,58 @@ public static class YamlConverter
1919 /// Mirrors the default System.Text.Json depth limit (64) that already bounds the JSON reader path,
2020 /// protecting the recursive conversion from stack exhaustion on deeply nested documents.
2121 /// </summary>
22- internal const int DefaultMaxDepth = 64 ;
22+ public const int DefaultMaxDepth = 64 ;
2323
2424 /// <summary>
2525 /// Default maximum number of JSON nodes that may be materialized from a single YAML document.
2626 /// Guards against YAML anchor/alias expansion ("billion laughs") attacks, where a tiny document
2727 /// expands exponentially when its shared node graph is materialized into an independent JSON tree.
28- /// Increase this only if legitimate large documents are being rejected.
2928 /// </summary>
30- internal const int DefaultMaxNodeCount = 5_000_000 ;
29+ public const int DefaultMaxNodeCount = 5_000_000 ;
30+
31+ private static int _maxDepth = DefaultMaxDepth ;
32+ private static int _maxNodeCount = DefaultMaxNodeCount ;
33+
34+ /// <summary>
35+ /// Gets or sets the maximum nesting depth allowed when converting a YAML node graph into JSON nodes.
36+ /// Defaults to <see cref="DefaultMaxDepth"/>. Raise this if legitimate deeply nested documents are
37+ /// being rejected, or lower it to fail faster when only shallow documents are expected.
38+ /// </summary>
39+ /// <exception cref="ArgumentOutOfRangeException">Thrown when set to a value less than 1.</exception>
40+ public static int MaxDepth
41+ {
42+ get => _maxDepth ;
43+ set
44+ {
45+ if ( value < 1 )
46+ {
47+ throw new ArgumentOutOfRangeException ( nameof ( value ) , "MaxDepth must be greater than zero." ) ;
48+ }
49+
50+ _maxDepth = value ;
51+ }
52+ }
53+
54+ /// <summary>
55+ /// Gets or sets the maximum number of JSON nodes that may be materialized from a single YAML document.
56+ /// Defaults to <see cref="DefaultMaxNodeCount"/>, guarding against YAML anchor/alias expansion
57+ /// ("billion laughs") attacks. Raise this if legitimate large documents are being rejected, or lower
58+ /// it to fail faster when only small documents are expected.
59+ /// </summary>
60+ /// <exception cref="ArgumentOutOfRangeException">Thrown when set to a value less than 1.</exception>
61+ public static int MaxNodeCount
62+ {
63+ get => _maxNodeCount ;
64+ set
65+ {
66+ if ( value < 1 )
67+ {
68+ throw new ArgumentOutOfRangeException ( nameof ( value ) , "MaxNodeCount must be greater than zero." ) ;
69+ }
70+
71+ _maxNodeCount = value ;
72+ }
73+ }
3174
3275 /// <summary>
3376 /// Tracks and enforces resource limits while converting a YAML node graph into JSON nodes,
@@ -39,7 +82,7 @@ private sealed class YamlConversionBudget
3982 private readonly int _maxNodeCount ;
4083 private int _nodeCount ;
4184
42- public YamlConversionBudget ( int maxDepth = DefaultMaxDepth , int maxNodeCount = DefaultMaxNodeCount )
85+ public YamlConversionBudget ( int maxDepth , int maxNodeCount )
4386 {
4487 _maxDepth = maxDepth ;
4588 _maxNodeCount = maxNodeCount ;
@@ -87,7 +130,7 @@ public static JsonNode ToJsonNode(this YamlDocument yaml)
87130 /// <exception cref="NotSupportedException">Thrown for YAML that is not compatible with JSON.</exception>
88131 public static JsonNode ToJsonNode ( this YamlNode yaml )
89132 {
90- return yaml . ToJsonNode ( new YamlConversionBudget ( ) , 0 ) ;
133+ return yaml . ToJsonNode ( new YamlConversionBudget ( MaxDepth , MaxNodeCount ) , 0 ) ;
91134 }
92135
93136 private static JsonNode ToJsonNode ( this YamlNode yaml , YamlConversionBudget budget , int depth )
@@ -130,7 +173,7 @@ public static YamlNode ToYamlNode(this JsonNode json)
130173 /// <returns></returns>
131174 public static JsonObject ToJsonObject ( this YamlMappingNode yaml )
132175 {
133- return yaml . ToJsonObject ( new YamlConversionBudget ( ) , 0 ) ;
176+ return yaml . ToJsonObject ( new YamlConversionBudget ( MaxDepth , MaxNodeCount ) , 0 ) ;
134177 }
135178
136179 private static JsonObject ToJsonObject ( this YamlMappingNode yaml , YamlConversionBudget budget , int depth )
@@ -160,7 +203,7 @@ private static YamlMappingNode ToYamlMapping(this JsonObject obj)
160203 /// <returns></returns>
161204 public static JsonArray ToJsonArray ( this YamlSequenceNode yaml )
162205 {
163- return yaml . ToJsonArray ( new YamlConversionBudget ( ) , 0 ) ;
206+ return yaml . ToJsonArray ( new YamlConversionBudget ( MaxDepth , MaxNodeCount ) , 0 ) ;
164207 }
165208
166209 private static JsonArray ToJsonArray ( this YamlSequenceNode yaml , YamlConversionBudget budget , int depth )
0 commit comments