@@ -18,6 +18,13 @@ namespace Microsoft.IdentityModel.Tokens.Json
18
18
{
19
19
internal static class JsonSerializerPrimitives
20
20
{
21
+ // This is not a general purpose JSON serializer. It is specifically
22
+ // made for the use in the IdentityModel libraries. As such, we can take a
23
+ // lower limit to both our reading and writing max depth.
24
+ // This number is the min between System.Text.Jsons default for
25
+ // writing and reading max depth.
26
+ const int MaxDepth = 64 ;
27
+
21
28
/// <summary>
22
29
/// Creates a JsonException that provides information on what went wrong
23
30
/// </summary>
@@ -119,8 +126,14 @@ public static JsonElement CreateJsonElement(string json)
119
126
#endif
120
127
}
121
128
122
- internal static object CreateObjectFromJsonElement ( JsonElement jsonElement )
129
+ internal static object CreateObjectFromJsonElement ( JsonElement jsonElement , int currentDepth )
123
130
{
131
+ if ( currentDepth >= MaxDepth )
132
+ throw new InvalidOperationException ( LogHelper . FormatInvariant (
133
+ LogMessages . IDX10815 ,
134
+ LogHelper . MarkAsNonPII ( currentDepth ) ,
135
+ LogHelper . MarkAsNonPII ( MaxDepth ) ) ) ;
136
+
124
137
if ( jsonElement . ValueKind == JsonValueKind . String )
125
138
{
126
139
if ( DateTime . TryParse ( jsonElement . GetString ( ) , CultureInfo . InvariantCulture , DateTimeStyles . RoundtripKind , out DateTime dateTime ) )
@@ -159,7 +172,9 @@ internal static object CreateObjectFromJsonElement(JsonElement jsonElement)
159
172
160
173
int index = 0 ;
161
174
foreach ( JsonElement j in jsonElement . EnumerateArray ( ) )
162
- items [ index ++ ] = CreateObjectFromJsonElement ( j ) ;
175
+ {
176
+ items [ index ++ ] = CreateObjectFromJsonElement ( j , currentDepth + 1 ) ;
177
+ }
163
178
164
179
return items ;
165
180
}
@@ -169,9 +184,12 @@ internal static object CreateObjectFromJsonElement(JsonElement jsonElement)
169
184
foreach ( JsonProperty property in jsonElement . EnumerateObject ( ) )
170
185
numItems ++ ;
171
186
187
+ int index = 0 ;
172
188
KeyValuePair < string , object > [ ] kvps = new KeyValuePair < string , object > [ numItems ] ;
173
189
foreach ( JsonProperty property in jsonElement . EnumerateObject ( ) )
174
- kvps [ numItems ++ ] = new KeyValuePair < string , object > ( property . Name , CreateObjectFromJsonElement ( property . Value ) ) ;
190
+ {
191
+ kvps [ index ++ ] = new KeyValuePair < string , object > ( property . Name , CreateObjectFromJsonElement ( property . Value , currentDepth + 1 ) ) ;
192
+ }
175
193
176
194
return kvps ;
177
195
}
@@ -181,6 +199,8 @@ internal static object CreateObjectFromJsonElement(JsonElement jsonElement)
181
199
182
200
public static bool TryCreateTypeFromJsonElement < T > ( JsonElement jsonElement , out T t )
183
201
{
202
+ int currentDepth = 0 ;
203
+
184
204
if ( typeof ( T ) == typeof ( string ) )
185
205
{
186
206
t = ( T ) ( object ) jsonElement . ToString ( ) ;
@@ -272,7 +292,9 @@ public static bool TryCreateTypeFromJsonElement<T>(JsonElement jsonElement, out
272
292
{
273
293
Dictionary < string , object > dictionary = new ( ) ;
274
294
foreach ( JsonProperty property in jsonElement . EnumerateObject ( ) )
275
- dictionary [ property . Name ] = CreateObjectFromJsonElement ( property . Value ) ;
295
+ {
296
+ dictionary [ property . Name ] = CreateObjectFromJsonElement ( property . Value , currentDepth + 1 ) ;
297
+ }
276
298
277
299
t = ( T ) ( object ) dictionary ;
278
300
return true ;
@@ -332,7 +354,9 @@ public static bool TryCreateTypeFromJsonElement<T>(JsonElement jsonElement, out
332
354
object [ ] items = new object [ numItems ] ;
333
355
numItems = 0 ;
334
356
foreach ( JsonElement j in jsonElement . EnumerateArray ( ) )
335
- items [ numItems ++ ] = CreateObjectFromJsonElement ( j ) ;
357
+ {
358
+ items [ numItems ++ ] = CreateObjectFromJsonElement ( j , currentDepth + 1 ) ;
359
+ }
336
360
337
361
t = ( T ) ( object ) items ;
338
362
return true ;
@@ -341,7 +365,9 @@ public static bool TryCreateTypeFromJsonElement<T>(JsonElement jsonElement, out
341
365
{
342
366
List < object > items = new ( ) ;
343
367
foreach ( JsonElement j in jsonElement . EnumerateArray ( ) )
344
- items . Add ( CreateObjectFromJsonElement ( j ) ) ;
368
+ {
369
+ items . Add ( CreateObjectFromJsonElement ( j , currentDepth + 1 ) ) ;
370
+ }
345
371
346
372
t = ( T ) ( object ) items ;
347
373
return true ;
@@ -350,7 +376,9 @@ public static bool TryCreateTypeFromJsonElement<T>(JsonElement jsonElement, out
350
376
{
351
377
Collection < object > items = new ( ) ;
352
378
foreach ( JsonElement j in jsonElement . EnumerateArray ( ) )
353
- items . Add ( CreateObjectFromJsonElement ( j ) ) ;
379
+ {
380
+ items . Add ( CreateObjectFromJsonElement ( j , currentDepth + 1 ) ) ;
381
+ }
354
382
355
383
t = ( T ) ( object ) items ;
356
384
return true ;
@@ -772,11 +800,14 @@ public static void WriteObjects(ref Utf8JsonWriter writer, IDictionary<string, o
772
800
/// general object serializer.
773
801
/// If a user needs to serialize a special value, then serialize the value into a JsonElement.
774
802
/// </summary>
775
- /// <param name="writer"></param>
776
- /// <param name="key"></param>
777
- /// <param name="obj"></param>
778
803
public static void WriteObject ( ref Utf8JsonWriter writer , string key , object obj )
779
804
{
805
+ if ( writer . CurrentDepth >= MaxDepth )
806
+ throw new InvalidOperationException ( LogHelper . FormatInvariant (
807
+ LogMessages . IDX10815 ,
808
+ LogHelper . MarkAsNonPII ( writer . CurrentDepth ) ,
809
+ LogHelper . MarkAsNonPII ( MaxDepth ) ) ) ;
810
+
780
811
if ( obj is null )
781
812
{
782
813
writer . WriteNull ( key ) ;
@@ -843,6 +874,12 @@ public static void WriteObject(ref Utf8JsonWriter writer, string key, object obj
843
874
/// <param name="obj"></param>
844
875
public static void WriteObjectValue ( ref Utf8JsonWriter writer , object obj )
845
876
{
877
+ if ( writer . CurrentDepth >= MaxDepth )
878
+ throw new InvalidOperationException ( LogHelper . FormatInvariant (
879
+ LogMessages . IDX10815 ,
880
+ LogHelper . MarkAsNonPII ( writer . CurrentDepth ) ,
881
+ LogHelper . MarkAsNonPII ( MaxDepth ) ) ) ;
882
+
846
883
Type objType = obj . GetType ( ) ;
847
884
848
885
if ( obj is string str )
0 commit comments