1
1
use core:: char;
2
2
use 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 ;
4
15
5
16
/// Representation of a demangled symbol name.
6
17
pub struct Demangle < ' a > {
@@ -58,13 +69,18 @@ pub fn demangle(s: &str) -> Result<(Demangle, &str), Invalid> {
58
69
59
70
impl < ' s > Display for Demangle < ' s > {
60
71
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
72
+ let mut remaining = MAX_APPROX_SIZE ;
61
73
let mut printer = Printer {
62
74
parser : Ok ( Parser {
63
75
sym : self . inner ,
64
76
next : 0 ,
65
77
} ) ,
66
- out : f,
78
+ out : LimitedFormatter {
79
+ remaining : & mut remaining,
80
+ inner : f,
81
+ } ,
67
82
bound_lifetime_depth : 0 ,
83
+ depth : 0 ,
68
84
} ;
69
85
printer. print_path ( true )
70
86
}
@@ -563,8 +579,9 @@ impl<'s> Parser<'s> {
563
579
564
580
struct Printer < ' a , ' b : ' a , ' s > {
565
581
parser : Result < Parser < ' s > , Invalid > ,
566
- out : & ' a mut fmt :: Formatter < ' b > ,
582
+ out : LimitedFormatter < ' a , ' b > ,
567
583
bound_lifetime_depth : u32 ,
584
+ depth : u32 ,
568
585
}
569
586
570
587
/// Mark the parser as errored, print `?` and return early.
@@ -603,12 +620,25 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
603
620
self . parser_mut ( ) . map ( |p| p. eat ( b) ) == Ok ( true )
604
621
}
605
622
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
+
606
632
/// Return a nested parser for a backref.
607
633
fn backref_printer < ' c > ( & ' c mut self ) -> Printer < ' c , ' b , ' s > {
608
634
Printer {
609
635
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
+ } ,
611
640
bound_lifetime_depth : self . bound_lifetime_depth ,
641
+ depth : self . depth ,
612
642
}
613
643
}
614
644
@@ -625,11 +655,11 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
625
655
// Try to print lifetimes alphabetically first.
626
656
if depth < 26 {
627
657
let c = ( b'a' + depth as u8 ) as char ;
628
- c. fmt ( self . out )
658
+ c. fmt ( self . out . inner )
629
659
} else {
630
660
// Use `'_123` after running out of letters.
631
661
self . out . write_str ( "_" ) ?;
632
- depth. fmt ( self . out )
662
+ depth. fmt ( self . out . inner )
633
663
}
634
664
}
635
665
None => invalid ! ( self ) ,
@@ -684,16 +714,17 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
684
714
}
685
715
686
716
fn print_path ( & mut self , in_value : bool ) -> fmt:: Result {
717
+ self . bump_depth ( ) ?;
687
718
let tag = parse ! ( self , next) ;
688
719
match tag {
689
720
b'C' => {
690
721
let dis = parse ! ( self , disambiguator) ;
691
722
let name = parse ! ( self , ident) ;
692
723
693
- name. fmt ( self . out ) ?;
694
- if !self . out . alternate ( ) {
724
+ name. fmt ( self . out . inner ) ?;
725
+ if !self . out . inner . alternate ( ) {
695
726
self . out . write_str ( "[" ) ?;
696
- fmt:: LowerHex :: fmt ( & dis, self . out ) ?;
727
+ fmt:: LowerHex :: fmt ( & dis, self . out . inner ) ?;
697
728
self . out . write_str ( "]" ) ?;
698
729
}
699
730
}
@@ -712,22 +743,22 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
712
743
match ns {
713
744
'C' => self . out . write_str ( "closure" ) ?,
714
745
'S' => self . out . write_str ( "shim" ) ?,
715
- _ => ns. fmt ( self . out ) ?,
746
+ _ => ns. fmt ( self . out . inner ) ?,
716
747
}
717
748
if !name. ascii . is_empty ( ) || !name. punycode . is_empty ( ) {
718
749
self . out . write_str ( ":" ) ?;
719
- name. fmt ( self . out ) ?;
750
+ name. fmt ( self . out . inner ) ?;
720
751
}
721
752
self . out . write_str ( "#" ) ?;
722
- dis. fmt ( self . out ) ?;
753
+ dis. fmt ( self . out . inner ) ?;
723
754
self . out . write_str ( "}" ) ?;
724
755
}
725
756
726
757
// Implementation-specific/unspecified namespaces.
727
758
None => {
728
759
if !name. ascii . is_empty ( ) || !name. punycode . is_empty ( ) {
729
760
self . out . write_str ( "::" ) ?;
730
- name. fmt ( self . out ) ?;
761
+ name. fmt ( self . out . inner ) ?;
731
762
}
732
763
}
733
764
}
@@ -761,6 +792,7 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
761
792
}
762
793
_ => invalid ! ( self ) ,
763
794
}
795
+ self . depth -= 1 ;
764
796
Ok ( ( ) )
765
797
}
766
798
@@ -782,6 +814,7 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
782
814
return self . out . write_str ( ty) ;
783
815
}
784
816
817
+ self . bump_depth ( ) ?;
785
818
match tag {
786
819
b'R' | b'Q' => {
787
820
self . out . write_str ( "&" ) ?;
@@ -898,6 +931,7 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
898
931
self . print_path ( false ) ?;
899
932
}
900
933
}
934
+ self . depth -= 1 ;
901
935
Ok ( ( ) )
902
936
}
903
937
@@ -932,7 +966,7 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
932
966
}
933
967
934
968
let name = parse ! ( self , ident) ;
935
- name. fmt ( self . out ) ?;
969
+ name. fmt ( self . out . inner ) ?;
936
970
self . out . write_str ( " = " ) ?;
937
971
self . print_type ( ) ?;
938
972
}
@@ -971,7 +1005,7 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
971
1005
_ => invalid ! ( self ) ,
972
1006
} ;
973
1007
974
- if !self . out . alternate ( ) {
1008
+ if !self . out . inner . alternate ( ) {
975
1009
self . out . write_str ( ": " ) ?;
976
1010
let ty = basic_type ( ty_tag) . unwrap ( ) ;
977
1011
self . out . write_str ( ty) ?;
@@ -993,7 +1027,7 @@ impl<'a, 'b, 's> Printer<'a, 'b, 's> {
993
1027
for c in hex. chars ( ) {
994
1028
v = ( v << 4 ) | ( c. to_digit ( 16 ) . unwrap ( ) as u64 ) ;
995
1029
}
996
- v. fmt ( self . out )
1030
+ v. fmt ( self . out . inner )
997
1031
}
998
1032
999
1033
fn print_const_int ( & mut self ) -> fmt:: Result {
@@ -1156,3 +1190,20 @@ mod tests {
1156
1190
) ;
1157
1191
}
1158
1192
}
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