@@ -20,6 +20,9 @@ use std::str::from_utf8;
2020pub struct Deserializer < ' b > {
2121 slice : & ' b [ u8 ] ,
2222 index : usize ,
23+
24+ /// Remaining depth until we hit the recursion limit
25+ remaining_depth : u8 ,
2326}
2427
2528enum StringLike < ' a > {
@@ -29,7 +32,11 @@ enum StringLike<'a> {
2932
3033impl < ' a > Deserializer < ' a > {
3134 fn new ( slice : & ' a [ u8 ] ) -> Deserializer < ' _ > {
32- Deserializer { slice, index : 0 }
35+ Deserializer {
36+ slice,
37+ index : 0 ,
38+ remaining_depth : 128 ,
39+ }
3340 }
3441
3542 fn eat_char ( & mut self ) {
@@ -286,16 +293,22 @@ impl<'a, 'de> de::Deserializer<'de> for &'a mut Deserializer<'de> {
286293 }
287294 }
288295 b'[' => {
289- self . eat_char ( ) ;
290- let ret = visitor. visit_seq ( SeqAccess :: new ( self ) ) ?;
296+ check_recursion ! {
297+ self . eat_char( ) ;
298+ let ret = visitor. visit_seq( SeqAccess :: new( self ) ) ;
299+ }
300+ let ret = ret?;
291301
292302 self . end_seq ( ) ?;
293303
294304 Ok ( ret)
295305 }
296306 b'{' => {
297- self . eat_char ( ) ;
298- let ret = visitor. visit_map ( MapAccess :: new ( self ) ) ?;
307+ check_recursion ! {
308+ self . eat_char( ) ;
309+ let ret = visitor. visit_map( MapAccess :: new( self ) ) ;
310+ }
311+ let ret = ret?;
299312
300313 self . end_map ( ) ?;
301314
@@ -548,8 +561,11 @@ impl<'a, 'de> de::Deserializer<'de> for &'a mut Deserializer<'de> {
548561 {
549562 match self . parse_whitespace ( ) . ok_or ( Error :: EofWhileParsingValue ) ? {
550563 b'[' => {
551- self . eat_char ( ) ;
552- let ret = visitor. visit_seq ( SeqAccess :: new ( self ) ) ?;
564+ check_recursion ! {
565+ self . eat_char( ) ;
566+ let ret = visitor. visit_seq( SeqAccess :: new( self ) ) ;
567+ }
568+ let ret = ret?;
553569
554570 self . end_seq ( ) ?;
555571
@@ -585,9 +601,11 @@ impl<'a, 'de> de::Deserializer<'de> for &'a mut Deserializer<'de> {
585601 let peek = self . parse_whitespace ( ) . ok_or ( Error :: EofWhileParsingValue ) ?;
586602
587603 if peek == b'{' {
588- self . eat_char ( ) ;
589-
590- let ret = visitor. visit_map ( MapAccess :: new ( self ) ) ?;
604+ check_recursion ! {
605+ self . eat_char( ) ;
606+ let ret = visitor. visit_map( MapAccess :: new( self ) ) ;
607+ }
608+ let ret = ret?;
591609
592610 self . end_map ( ) ?;
593611
@@ -623,8 +641,11 @@ impl<'a, 'de> de::Deserializer<'de> for &'a mut Deserializer<'de> {
623641 b'"' => visitor. visit_enum ( UnitVariantAccess :: new ( self ) ) ,
624642 // if it is a struct enum
625643 b'{' => {
626- self . eat_char ( ) ;
627- visitor. visit_enum ( StructVariantAccess :: new ( self ) )
644+ check_recursion ! {
645+ self . eat_char( ) ;
646+ let value = visitor. visit_enum( StructVariantAccess :: new( self ) ) ;
647+ }
648+ value
628649 }
629650 _ => Err ( Error :: ExpectedSomeIdent ) ,
630651 }
@@ -684,6 +705,20 @@ where
684705 from_slice ( s. as_bytes ( ) )
685706}
686707
708+ macro_rules! check_recursion {
709+ ( $this: ident $( $body: tt) * ) => {
710+ $this. remaining_depth -= 1 ;
711+ if $this. remaining_depth == 0 {
712+ return Err ( $crate:: de:: Error :: RecursionLimitExceeded ) ;
713+ }
714+
715+ $this $( $body) *
716+
717+ $this. remaining_depth += 1 ;
718+ } ;
719+ }
720+ pub ( crate ) use check_recursion;
721+
687722#[ cfg( test) ]
688723mod tests {
689724 use super :: from_str;
0 commit comments