@@ -21,6 +21,9 @@ use self::seq::SeqAccess;
2121pub struct Deserializer < ' b > {
2222 slice : & ' b [ u8 ] ,
2323 index : usize ,
24+
25+ /// Remaining depth until we hit the recursion limit
26+ remaining_depth : u8 ,
2427}
2528
2629enum StringLike < ' a > {
@@ -30,7 +33,11 @@ enum StringLike<'a> {
3033
3134impl < ' a > Deserializer < ' a > {
3235 fn new ( slice : & ' a [ u8 ] ) -> Deserializer < ' _ > {
33- Deserializer { slice, index : 0 }
36+ Deserializer {
37+ slice,
38+ index : 0 ,
39+ remaining_depth : 128 ,
40+ }
3441 }
3542
3643 fn eat_char ( & mut self ) {
@@ -287,16 +294,22 @@ impl<'a, 'de> de::Deserializer<'de> for &'a mut Deserializer<'de> {
287294 }
288295 }
289296 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?;
292302
293303 self . end_seq ( ) ?;
294304
295305 Ok ( ret)
296306 }
297307 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?;
300313
301314 self . end_map ( ) ?;
302315
@@ -513,8 +526,11 @@ impl<'a, 'de> de::Deserializer<'de> for &'a mut Deserializer<'de> {
513526 {
514527 match self . parse_whitespace ( ) . ok_or ( Error :: EofWhileParsingValue ) ? {
515528 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?;
518534
519535 self . end_seq ( ) ?;
520536
@@ -550,9 +566,11 @@ impl<'a, 'de> de::Deserializer<'de> for &'a mut Deserializer<'de> {
550566 let peek = self . parse_whitespace ( ) . ok_or ( Error :: EofWhileParsingValue ) ?;
551567
552568 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?;
556574
557575 self . end_map ( ) ?;
558576
@@ -588,8 +606,11 @@ impl<'a, 'de> de::Deserializer<'de> for &'a mut Deserializer<'de> {
588606 b'"' => visitor. visit_enum ( UnitVariantAccess :: new ( self ) ) ,
589607 // if it is a struct enum
590608 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
593614 }
594615 _ => Err ( Error :: ExpectedSomeIdent ) ,
595616 }
@@ -649,6 +670,20 @@ where
649670 from_slice ( s. as_bytes ( ) )
650671}
651672
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+
652687#[ cfg( test) ]
653688mod tests {
654689 use super :: from_str;
0 commit comments