@@ -21,6 +21,9 @@ use self::seq::SeqAccess;
21
21
pub struct Deserializer < ' b > {
22
22
slice : & ' b [ u8 ] ,
23
23
index : usize ,
24
+
25
+ /// Remaining depth until we hit the recursion limit
26
+ remaining_depth : u8 ,
24
27
}
25
28
26
29
enum StringLike < ' a > {
@@ -30,7 +33,11 @@ enum StringLike<'a> {
30
33
31
34
impl < ' a > Deserializer < ' a > {
32
35
fn new ( slice : & ' a [ u8 ] ) -> Deserializer < ' _ > {
33
- Deserializer { slice, index : 0 }
36
+ Deserializer {
37
+ slice,
38
+ index : 0 ,
39
+ remaining_depth : 128 ,
40
+ }
34
41
}
35
42
36
43
fn eat_char ( & mut self ) {
@@ -287,16 +294,22 @@ impl<'a, 'de> de::Deserializer<'de> for &'a mut Deserializer<'de> {
287
294
}
288
295
}
289
296
b'[' => {
290
- self . eat_char ( ) ;
291
- let ret = visitor. visit_seq ( SeqAccess :: new ( self ) ) ?;
297
+ check_recursion ! {
298
+ self . eat_char( ) ;
299
+ let ret = visitor. visit_seq( SeqAccess :: new( self ) ) ;
300
+ }
301
+ let ret = ret?;
292
302
293
303
self . end_seq ( ) ?;
294
304
295
305
Ok ( ret)
296
306
}
297
307
b'{' => {
298
- self . eat_char ( ) ;
299
- let ret = visitor. visit_map ( MapAccess :: new ( self ) ) ?;
308
+ check_recursion ! {
309
+ self . eat_char( ) ;
310
+ let ret = visitor. visit_map( MapAccess :: new( self ) ) ;
311
+ }
312
+ let ret = ret?;
300
313
301
314
self . end_map ( ) ?;
302
315
@@ -513,8 +526,11 @@ impl<'a, 'de> de::Deserializer<'de> for &'a mut Deserializer<'de> {
513
526
{
514
527
match self . parse_whitespace ( ) . ok_or ( Error :: EofWhileParsingValue ) ? {
515
528
b'[' => {
516
- self . eat_char ( ) ;
517
- let ret = visitor. visit_seq ( SeqAccess :: new ( self ) ) ?;
529
+ check_recursion ! {
530
+ self . eat_char( ) ;
531
+ let ret = visitor. visit_seq( SeqAccess :: new( self ) ) ;
532
+ }
533
+ let ret = ret?;
518
534
519
535
self . end_seq ( ) ?;
520
536
@@ -550,9 +566,11 @@ impl<'a, 'de> de::Deserializer<'de> for &'a mut Deserializer<'de> {
550
566
let peek = self . parse_whitespace ( ) . ok_or ( Error :: EofWhileParsingValue ) ?;
551
567
552
568
if peek == b'{' {
553
- self . eat_char ( ) ;
554
-
555
- let ret = visitor. visit_map ( MapAccess :: new ( self ) ) ?;
569
+ check_recursion ! {
570
+ self . eat_char( ) ;
571
+ let ret = visitor. visit_map( MapAccess :: new( self ) ) ;
572
+ }
573
+ let ret = ret?;
556
574
557
575
self . end_map ( ) ?;
558
576
@@ -588,8 +606,11 @@ impl<'a, 'de> de::Deserializer<'de> for &'a mut Deserializer<'de> {
588
606
b'"' => visitor. visit_enum ( UnitVariantAccess :: new ( self ) ) ,
589
607
// if it is a struct enum
590
608
b'{' => {
591
- self . eat_char ( ) ;
592
- visitor. visit_enum ( StructVariantAccess :: new ( self ) )
609
+ check_recursion ! {
610
+ self . eat_char( ) ;
611
+ let value = visitor. visit_enum( StructVariantAccess :: new( self ) ) ;
612
+ }
613
+ value
593
614
}
594
615
_ => Err ( Error :: ExpectedSomeIdent ) ,
595
616
}
@@ -649,6 +670,20 @@ where
649
670
from_slice ( s. as_bytes ( ) )
650
671
}
651
672
673
+ macro_rules! check_recursion {
674
+ ( $this: ident $( $body: tt) * ) => {
675
+ $this. remaining_depth -= 1 ;
676
+ if $this. remaining_depth == 0 {
677
+ return Err ( $crate:: de:: Error :: RecursionLimitExceeded ) ;
678
+ }
679
+
680
+ $this $( $body) *
681
+
682
+ $this. remaining_depth += 1 ;
683
+ } ;
684
+ }
685
+ pub ( crate ) use check_recursion;
686
+
652
687
#[ cfg( test) ]
653
688
mod tests {
654
689
use super :: from_str;
0 commit comments