11use core:: char;
22use core:: fmt;
3- use core:: fmt:: Display ;
3+ use core:: fmt:: { Display , Write } ;
4+
5+ // Maximum recursion depth when printing symbols before we just bail out saying
6+ // "this symbol is invalid"
7+ const MAX_DEPTH : u32 = 1_000 ;
8+
9+ // Approximately the maximum size of the symbol that we'll print. This is
10+ // approximate because it only limits calls writing to `LimitedFormatter`, but
11+ // not all writes exclusively go through `LimitedFormatter`. Some writes go
12+ // directly to the underlying formatter, but when that happens we always write
13+ // at least a little to the `LimitedFormatter`.
14+ const MAX_APPROX_SIZE : usize = 1_000_000 ;
415
516/// Representation of a demangled symbol name.
617pub struct Demangle < ' a > {
@@ -58,13 +69,18 @@ pub fn demangle(s: &str) -> Result<(Demangle, &str), Invalid> {
5869
5970impl < ' s > Display for Demangle < ' s > {
6071 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
72+ let mut remaining = MAX_APPROX_SIZE ;
6173 let mut printer = Printer {
6274 parser : Ok ( Parser {
6375 sym : self . inner ,
6476 next : 0 ,
6577 } ) ,
66- out : f,
78+ out : LimitedFormatter {
79+ remaining : & mut remaining,
80+ inner : f,
81+ } ,
6782 bound_lifetime_depth : 0 ,
83+ depth : 0 ,
6884 } ;
6985 printer. print_path ( true )
7086 }
@@ -563,8 +579,9 @@ impl<'s> Parser<'s> {
563579
564580struct Printer < ' a , ' b : ' a , ' s > {
565581 parser : Result < Parser < ' s > , Invalid > ,
566- out : & ' a mut fmt :: Formatter < ' b > ,
582+ out : LimitedFormatter < ' a , ' b > ,
567583 bound_lifetime_depth : u32 ,
584+ depth : u32 ,
568585}
569586
570587/// Mark the parser as errored, print `?` and return early.
@@ -603,12 +620,25 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
603620 self . parser_mut ( ) . map ( |p| p. eat ( b) ) == Ok ( true )
604621 }
605622
623+ fn bump_depth ( & mut self ) -> fmt:: Result {
624+ self . depth += 1 ;
625+ if self . depth > MAX_DEPTH {
626+ Err ( fmt:: Error )
627+ } else {
628+ Ok ( ( ) )
629+ }
630+ }
631+
606632 /// Return a nested parser for a backref.
607633 fn backref_printer < ' c > ( & ' c mut self ) -> Printer < ' c , ' b , ' s > {
608634 Printer {
609635 parser : self . parser_mut ( ) . and_then ( |p| p. backref ( ) ) ,
610- out : self . out ,
636+ out : LimitedFormatter {
637+ remaining : self . out . remaining ,
638+ inner : self . out . inner ,
639+ } ,
611640 bound_lifetime_depth : self . bound_lifetime_depth ,
641+ depth : self . depth ,
612642 }
613643 }
614644
@@ -625,11 +655,11 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
625655 // Try to print lifetimes alphabetically first.
626656 if depth < 26 {
627657 let c = ( b'a' + depth as u8 ) as char ;
628- c. fmt ( self . out )
658+ c. fmt ( self . out . inner )
629659 } else {
630660 // Use `'_123` after running out of letters.
631661 self . out . write_str ( "_" ) ?;
632- depth. fmt ( self . out )
662+ depth. fmt ( self . out . inner )
633663 }
634664 }
635665 None => invalid ! ( self ) ,
@@ -684,16 +714,17 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
684714 }
685715
686716 fn print_path ( & mut self , in_value : bool ) -> fmt:: Result {
717+ self . bump_depth ( ) ?;
687718 let tag = parse ! ( self , next) ;
688719 match tag {
689720 b'C' => {
690721 let dis = parse ! ( self , disambiguator) ;
691722 let name = parse ! ( self , ident) ;
692723
693- name. fmt ( self . out ) ?;
694- if !self . out . alternate ( ) {
724+ name. fmt ( self . out . inner ) ?;
725+ if !self . out . inner . alternate ( ) {
695726 self . out . write_str ( "[" ) ?;
696- fmt:: LowerHex :: fmt ( & dis, self . out ) ?;
727+ fmt:: LowerHex :: fmt ( & dis, self . out . inner ) ?;
697728 self . out . write_str ( "]" ) ?;
698729 }
699730 }
@@ -712,22 +743,22 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
712743 match ns {
713744 'C' => self . out . write_str ( "closure" ) ?,
714745 'S' => self . out . write_str ( "shim" ) ?,
715- _ => ns. fmt ( self . out ) ?,
746+ _ => ns. fmt ( self . out . inner ) ?,
716747 }
717748 if !name. ascii . is_empty ( ) || !name. punycode . is_empty ( ) {
718749 self . out . write_str ( ":" ) ?;
719- name. fmt ( self . out ) ?;
750+ name. fmt ( self . out . inner ) ?;
720751 }
721752 self . out . write_str ( "#" ) ?;
722- dis. fmt ( self . out ) ?;
753+ dis. fmt ( self . out . inner ) ?;
723754 self . out . write_str ( "}" ) ?;
724755 }
725756
726757 // Implementation-specific/unspecified namespaces.
727758 None => {
728759 if !name. ascii . is_empty ( ) || !name. punycode . is_empty ( ) {
729760 self . out . write_str ( "::" ) ?;
730- name. fmt ( self . out ) ?;
761+ name. fmt ( self . out . inner ) ?;
731762 }
732763 }
733764 }
@@ -761,6 +792,7 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
761792 }
762793 _ => invalid ! ( self ) ,
763794 }
795+ self . depth -= 1 ;
764796 Ok ( ( ) )
765797 }
766798
@@ -782,6 +814,7 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
782814 return self . out . write_str ( ty) ;
783815 }
784816
817+ self . bump_depth ( ) ?;
785818 match tag {
786819 b'R' | b'Q' => {
787820 self . out . write_str ( "&" ) ?;
@@ -898,6 +931,7 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
898931 self . print_path ( false ) ?;
899932 }
900933 }
934+ self . depth -= 1 ;
901935 Ok ( ( ) )
902936 }
903937
@@ -932,7 +966,7 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
932966 }
933967
934968 let name = parse ! ( self , ident) ;
935- name. fmt ( self . out ) ?;
969+ name. fmt ( self . out . inner ) ?;
936970 self . out . write_str ( " = " ) ?;
937971 self . print_type ( ) ?;
938972 }
@@ -971,7 +1005,7 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
9711005 _ => invalid ! ( self ) ,
9721006 } ;
9731007
974- if !self . out . alternate ( ) {
1008+ if !self . out . inner . alternate ( ) {
9751009 self . out . write_str ( ": " ) ?;
9761010 let ty = basic_type ( ty_tag) . unwrap ( ) ;
9771011 self . out . write_str ( ty) ?;
@@ -993,7 +1027,7 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
9931027 for c in hex. chars ( ) {
9941028 v = ( v << 4 ) | ( c. to_digit ( 16 ) . unwrap ( ) as u64 ) ;
9951029 }
996- v. fmt ( self . out )
1030+ v. fmt ( self . out . inner )
9971031 }
9981032
9991033 fn print_const_int ( & mut self ) -> fmt:: Result {
@@ -1156,3 +1190,20 @@ mod tests {
11561190 ) ;
11571191 }
11581192}
1193+
1194+ struct LimitedFormatter < ' a , ' b > {
1195+ remaining : & ' a mut usize ,
1196+ inner : & ' a mut fmt:: Formatter < ' b > ,
1197+ }
1198+
1199+ impl Write for LimitedFormatter < ' _ , ' _ > {
1200+ fn write_str ( & mut self , s : & str ) -> fmt:: Result {
1201+ match self . remaining . checked_sub ( s. len ( ) ) {
1202+ Some ( amt) => {
1203+ * self . remaining = amt;
1204+ self . inner . write_str ( s)
1205+ }
1206+ None => Err ( fmt:: Error ) ,
1207+ }
1208+ }
1209+ }
0 commit comments