1 use core::char;
2 use core::fmt;
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;
15 
16 /// Representation of a demangled symbol name.
17 pub struct Demangle<'a> {
18     inner: &'a str,
19 }
20 
21 /// De-mangles a Rust symbol into a more readable version
22 ///
23 /// This function will take a **mangled** symbol and return a value. When printed,
24 /// the de-mangled version will be written. If the symbol does not look like
25 /// a mangled symbol, the original value will be written instead.
demangle(s: &str) -> Result<(Demangle, &str), Invalid>26 pub fn demangle(s: &str) -> Result<(Demangle, &str), Invalid> {
27     // First validate the symbol. If it doesn't look like anything we're
28     // expecting, we just print it literally. Note that we must handle non-Rust
29     // symbols because we could have any function in the backtrace.
30     let inner;
31     if s.len() > 2 && s.starts_with("_R") {
32         inner = &s[2..];
33     } else if s.len() > 1 && s.starts_with('R') {
34         // On Windows, dbghelp strips leading underscores, so we accept "R..."
35         // form too.
36         inner = &s[1..];
37     } else if s.len() > 3 && s.starts_with("__R") {
38         // On OSX, symbols are prefixed with an extra _
39         inner = &s[3..];
40     } else {
41         return Err(Invalid);
42     }
43 
44     // Paths always start with uppercase characters.
45     match inner.as_bytes()[0] {
46         b'A'..=b'Z' => {}
47         _ => return Err(Invalid),
48     }
49 
50     // only work with ascii text
51     if inner.bytes().any(|c| c & 0x80 != 0) {
52         return Err(Invalid);
53     }
54 
55     // Verify that the symbol is indeed a valid path.
56     let mut parser = Parser {
57         sym: inner,
58         next: 0,
59     };
60     parser.skip_path()?;
61 
62     // Instantiating crate (paths always start with uppercase characters).
63     if let Some(&(b'A'..=b'Z')) = parser.sym.as_bytes().get(parser.next) {
64         parser.skip_path()?;
65     }
66 
67     Ok((Demangle { inner }, &parser.sym[parser.next..]))
68 }
69 
70 impl<'s> Display for Demangle<'s> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result71     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
72         let mut remaining = MAX_APPROX_SIZE;
73         let mut printer = Printer {
74             parser: Ok(Parser {
75                 sym: self.inner,
76                 next: 0,
77             }),
78             out: LimitedFormatter {
79                 remaining: &mut remaining,
80                 inner: f,
81             },
82             bound_lifetime_depth: 0,
83             depth: 0,
84         };
85         printer.print_path(true)
86     }
87 }
88 
89 #[derive(PartialEq, Eq)]
90 pub struct Invalid;
91 
92 struct Ident<'s> {
93     /// ASCII part of the identifier.
94     ascii: &'s str,
95     /// Punycode insertion codes for Unicode codepoints, if any.
96     punycode: &'s str,
97 }
98 
99 const SMALL_PUNYCODE_LEN: usize = 128;
100 
101 impl<'s> Ident<'s> {
102     /// Attempt to decode punycode on the stack (allocation-free),
103     /// and pass the char slice to the closure, if successful.
104     /// This supports up to `SMALL_PUNYCODE_LEN` characters.
try_small_punycode_decode<F: FnOnce(&[char]) -> R, R>(&self, f: F) -> Option<R>105     fn try_small_punycode_decode<F: FnOnce(&[char]) -> R, R>(&self, f: F) -> Option<R> {
106         let mut out = ['\0'; SMALL_PUNYCODE_LEN];
107         let mut out_len = 0;
108         let r = self.punycode_decode(|i, c| {
109             // Check there's space left for another character.
110             out.get(out_len).ok_or(())?;
111 
112             // Move the characters after the insert position.
113             let mut j = out_len;
114             out_len += 1;
115 
116             while j > i {
117                 out[j] = out[j - 1];
118                 j -= 1;
119             }
120 
121             // Insert the new character.
122             out[i] = c;
123 
124             Ok(())
125         });
126         if r.is_ok() {
127             Some(f(&out[..out_len]))
128         } else {
129             None
130         }
131     }
132 
133     /// Decode punycode as insertion positions and characters
134     /// and pass them to the closure, which can return `Err(())`
135     /// to stop the decoding process.
punycode_decode<F: FnMut(usize, char) -> Result<(), ()>>( &self, mut insert: F, ) -> Result<(), ()>136     fn punycode_decode<F: FnMut(usize, char) -> Result<(), ()>>(
137         &self,
138         mut insert: F,
139     ) -> Result<(), ()> {
140         let mut punycode_bytes = self.punycode.bytes().peekable();
141         if punycode_bytes.peek().is_none() {
142             return Err(());
143         }
144 
145         let mut len = 0;
146 
147         // Populate initial output from ASCII fragment.
148         for c in self.ascii.chars() {
149             insert(len, c)?;
150             len += 1;
151         }
152 
153         // Punycode parameters and initial state.
154         let base = 36;
155         let t_min = 1;
156         let t_max = 26;
157         let skew = 38;
158         let mut damp = 700;
159         let mut bias = 72;
160         let mut i: usize = 0;
161         let mut n: usize = 0x80;
162 
163         loop {
164             // Read one delta value.
165             let mut delta: usize = 0;
166             let mut w = 1;
167             let mut k: usize = 0;
168             loop {
169                 use core::cmp::{max, min};
170 
171                 k += base;
172                 let t = min(max(k.saturating_sub(bias), t_min), t_max);
173 
174                 let d = match punycode_bytes.next() {
175                     Some(d @ b'a'..=b'z') => d - b'a',
176                     Some(d @ b'0'..=b'9') => 26 + (d - b'0'),
177                     _ => return Err(()),
178                 };
179                 let d = d as usize;
180                 delta = delta.checked_add(d.checked_mul(w).ok_or(())?).ok_or(())?;
181                 if d < t {
182                     break;
183                 }
184                 w = w.checked_mul(base - t).ok_or(())?;
185             }
186 
187             // Compute the new insert position and character.
188             len += 1;
189             i = i.checked_add(delta).ok_or(())?;
190             n = n.checked_add(i / len).ok_or(())?;
191             i %= len;
192 
193             let n_u32 = n as u32;
194             let c = if n_u32 as usize == n {
195                 char::from_u32(n_u32).ok_or(())?
196             } else {
197                 return Err(());
198             };
199 
200             // Insert the new character and increment the insert position.
201             insert(i, c)?;
202             i += 1;
203 
204             // If there are no more deltas, decoding is complete.
205             if punycode_bytes.peek().is_none() {
206                 return Ok(());
207             }
208 
209             // Perform bias adaptation.
210             delta /= damp;
211             damp = 2;
212 
213             delta += delta / len;
214             let mut k = 0;
215             while delta > ((base - t_min) * t_max) / 2 {
216                 delta /= base - t_min;
217                 k += base;
218             }
219             bias = k + ((base - t_min + 1) * delta) / (delta + skew);
220         }
221     }
222 }
223 
224 impl<'s> Display for Ident<'s> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result225     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
226         self.try_small_punycode_decode(|chars| {
227             for &c in chars {
228                 c.fmt(f)?;
229             }
230             Ok(())
231         })
232         .unwrap_or_else(|| {
233             if !self.punycode.is_empty() {
234                 f.write_str("punycode{")?;
235 
236                 // Reconstruct a standard Punycode encoding,
237                 // by using `-` as the separator.
238                 if !self.ascii.is_empty() {
239                     f.write_str(self.ascii)?;
240                     f.write_str("-")?;
241                 }
242                 f.write_str(self.punycode)?;
243 
244                 f.write_str("}")
245             } else {
246                 f.write_str(self.ascii)
247             }
248         })
249     }
250 }
251 
basic_type(tag: u8) -> Option<&'static str>252 fn basic_type(tag: u8) -> Option<&'static str> {
253     Some(match tag {
254         b'b' => "bool",
255         b'c' => "char",
256         b'e' => "str",
257         b'u' => "()",
258         b'a' => "i8",
259         b's' => "i16",
260         b'l' => "i32",
261         b'x' => "i64",
262         b'n' => "i128",
263         b'i' => "isize",
264         b'h' => "u8",
265         b't' => "u16",
266         b'm' => "u32",
267         b'y' => "u64",
268         b'o' => "u128",
269         b'j' => "usize",
270         b'f' => "f32",
271         b'd' => "f64",
272         b'z' => "!",
273         b'p' => "_",
274         b'v' => "...",
275 
276         _ => return None,
277     })
278 }
279 
280 struct Parser<'s> {
281     sym: &'s str,
282     next: usize,
283 }
284 
285 impl<'s> Parser<'s> {
peek(&self) -> Option<u8>286     fn peek(&self) -> Option<u8> {
287         self.sym.as_bytes().get(self.next).cloned()
288     }
289 
eat(&mut self, b: u8) -> bool290     fn eat(&mut self, b: u8) -> bool {
291         if self.peek() == Some(b) {
292             self.next += 1;
293             true
294         } else {
295             false
296         }
297     }
298 
next(&mut self) -> Result<u8, Invalid>299     fn next(&mut self) -> Result<u8, Invalid> {
300         let b = self.peek().ok_or(Invalid)?;
301         self.next += 1;
302         Ok(b)
303     }
304 
hex_nibbles(&mut self) -> Result<&'s str, Invalid>305     fn hex_nibbles(&mut self) -> Result<&'s str, Invalid> {
306         let start = self.next;
307         loop {
308             match self.next()? {
309                 b'0'..=b'9' | b'a'..=b'f' => {}
310                 b'_' => break,
311                 _ => return Err(Invalid),
312             }
313         }
314         Ok(&self.sym[start..self.next - 1])
315     }
316 
digit_10(&mut self) -> Result<u8, Invalid>317     fn digit_10(&mut self) -> Result<u8, Invalid> {
318         let d = match self.peek() {
319             Some(d @ b'0'..=b'9') => d - b'0',
320             _ => return Err(Invalid),
321         };
322         self.next += 1;
323         Ok(d)
324     }
325 
digit_62(&mut self) -> Result<u8, Invalid>326     fn digit_62(&mut self) -> Result<u8, Invalid> {
327         let d = match self.peek() {
328             Some(d @ b'0'..=b'9') => d - b'0',
329             Some(d @ b'a'..=b'z') => 10 + (d - b'a'),
330             Some(d @ b'A'..=b'Z') => 10 + 26 + (d - b'A'),
331             _ => return Err(Invalid),
332         };
333         self.next += 1;
334         Ok(d)
335     }
336 
integer_62(&mut self) -> Result<u64, Invalid>337     fn integer_62(&mut self) -> Result<u64, Invalid> {
338         if self.eat(b'_') {
339             return Ok(0);
340         }
341 
342         let mut x: u64 = 0;
343         while !self.eat(b'_') {
344             let d = self.digit_62()? as u64;
345             x = x.checked_mul(62).ok_or(Invalid)?;
346             x = x.checked_add(d).ok_or(Invalid)?;
347         }
348         x.checked_add(1).ok_or(Invalid)
349     }
350 
opt_integer_62(&mut self, tag: u8) -> Result<u64, Invalid>351     fn opt_integer_62(&mut self, tag: u8) -> Result<u64, Invalid> {
352         if !self.eat(tag) {
353             return Ok(0);
354         }
355         self.integer_62()?.checked_add(1).ok_or(Invalid)
356     }
357 
disambiguator(&mut self) -> Result<u64, Invalid>358     fn disambiguator(&mut self) -> Result<u64, Invalid> {
359         self.opt_integer_62(b's')
360     }
361 
namespace(&mut self) -> Result<Option<char>, Invalid>362     fn namespace(&mut self) -> Result<Option<char>, Invalid> {
363         match self.next()? {
364             // Special namespaces, like closures and shims.
365             ns @ b'A'..=b'Z' => Ok(Some(ns as char)),
366 
367             // Implementation-specific/unspecified namespaces.
368             b'a'..=b'z' => Ok(None),
369 
370             _ => Err(Invalid),
371         }
372     }
373 
backref(&mut self) -> Result<Parser<'s>, Invalid>374     fn backref(&mut self) -> Result<Parser<'s>, Invalid> {
375         let s_start = self.next - 1;
376         let i = self.integer_62()?;
377         if i >= s_start as u64 {
378             return Err(Invalid);
379         }
380         Ok(Parser {
381             sym: self.sym,
382             next: i as usize,
383         })
384     }
385 
ident(&mut self) -> Result<Ident<'s>, Invalid>386     fn ident(&mut self) -> Result<Ident<'s>, Invalid> {
387         let is_punycode = self.eat(b'u');
388         let mut len = self.digit_10()? as usize;
389         if len != 0 {
390             while let Ok(d) = self.digit_10() {
391                 len = len.checked_mul(10).ok_or(Invalid)?;
392                 len = len.checked_add(d as usize).ok_or(Invalid)?;
393             }
394         }
395 
396         // Skip past the optional `_` separator.
397         self.eat(b'_');
398 
399         let start = self.next;
400         self.next = self.next.checked_add(len).ok_or(Invalid)?;
401         if self.next > self.sym.len() {
402             return Err(Invalid);
403         }
404 
405         let ident = &self.sym[start..self.next];
406 
407         if is_punycode {
408             let ident = match ident.bytes().rposition(|b| b == b'_') {
409                 Some(i) => Ident {
410                     ascii: &ident[..i],
411                     punycode: &ident[i + 1..],
412                 },
413                 None => Ident {
414                     ascii: "",
415                     punycode: ident,
416                 },
417             };
418             if ident.punycode.is_empty() {
419                 return Err(Invalid);
420             }
421             Ok(ident)
422         } else {
423             Ok(Ident {
424                 ascii: ident,
425                 punycode: "",
426             })
427         }
428     }
429 
skip_path(&mut self) -> Result<(), Invalid>430     fn skip_path(&mut self) -> Result<(), Invalid> {
431         match self.next()? {
432             b'C' => {
433                 self.disambiguator()?;
434                 self.ident()?;
435             }
436             b'N' => {
437                 self.namespace()?;
438                 self.skip_path()?;
439                 self.disambiguator()?;
440                 self.ident()?;
441             }
442             b'M' => {
443                 self.disambiguator()?;
444                 self.skip_path()?;
445                 self.skip_type()?;
446             }
447             b'X' => {
448                 self.disambiguator()?;
449                 self.skip_path()?;
450                 self.skip_type()?;
451                 self.skip_path()?;
452             }
453             b'Y' => {
454                 self.skip_type()?;
455                 self.skip_path()?;
456             }
457             b'I' => {
458                 self.skip_path()?;
459                 while !self.eat(b'E') {
460                     self.skip_generic_arg()?;
461                 }
462             }
463             b'B' => {
464                 self.backref()?;
465             }
466             _ => return Err(Invalid),
467         }
468         Ok(())
469     }
470 
skip_generic_arg(&mut self) -> Result<(), Invalid>471     fn skip_generic_arg(&mut self) -> Result<(), Invalid> {
472         if self.eat(b'L') {
473             self.integer_62()?;
474             Ok(())
475         } else if self.eat(b'K') {
476             self.skip_const()
477         } else {
478             self.skip_type()
479         }
480     }
481 
skip_type(&mut self) -> Result<(), Invalid>482     fn skip_type(&mut self) -> Result<(), Invalid> {
483         match self.next()? {
484             tag if basic_type(tag).is_some() => {}
485 
486             b'R' | b'Q' => {
487                 if self.eat(b'L') {
488                     self.integer_62()?;
489                 }
490                 self.skip_type()?;
491             }
492             b'P' | b'O' | b'S' => self.skip_type()?,
493             b'A' => {
494                 self.skip_type()?;
495                 self.skip_const()?;
496             }
497             b'T' => {
498                 while !self.eat(b'E') {
499                     self.skip_type()?;
500                 }
501             }
502             b'F' => {
503                 let _binder = self.opt_integer_62(b'G')?;
504                 let _is_unsafe = self.eat(b'U');
505                 if self.eat(b'K') {
506                     let c_abi = self.eat(b'C');
507                     if !c_abi {
508                         let abi = self.ident()?;
509                         if abi.ascii.is_empty() || !abi.punycode.is_empty() {
510                             return Err(Invalid);
511                         }
512                     }
513                 }
514                 while !self.eat(b'E') {
515                     self.skip_type()?;
516                 }
517                 self.skip_type()?;
518             }
519             b'D' => {
520                 let _binder = self.opt_integer_62(b'G')?;
521                 while !self.eat(b'E') {
522                     self.skip_path()?;
523                     while self.eat(b'p') {
524                         self.ident()?;
525                         self.skip_type()?;
526                     }
527                 }
528                 if !self.eat(b'L') {
529                     return Err(Invalid);
530                 }
531                 self.integer_62()?;
532             }
533             b'B' => {
534                 self.backref()?;
535             }
536             _ => {
537                 // Go back to the tag, so `skip_path` also sees it.
538                 self.next -= 1;
539                 self.skip_path()?;
540             }
541         }
542         Ok(())
543     }
544 
skip_const(&mut self) -> Result<(), Invalid>545     fn skip_const(&mut self) -> Result<(), Invalid> {
546         if self.eat(b'B') {
547             self.backref()?;
548             return Ok(());
549         }
550 
551         let ty_tag = self.next()?;
552 
553         if ty_tag == b'p' {
554             // We don't encode the type if the value is a placeholder.
555             return Ok(());
556         }
557 
558         match ty_tag {
559             // Unsigned integer types.
560             b'h' | b't' | b'm' | b'y' | b'o' | b'j' |
561             // Bool.
562             b'b' |
563             // Char.
564             b'c' => {}
565 
566             // Signed integer types.
567             b'a' | b's' | b'l' | b'x' | b'n' | b'i' => {
568                 // Negation on signed integers.
569                 let _ = self.eat(b'n');
570             }
571 
572             _ => return Err(Invalid),
573         }
574 
575         self.hex_nibbles()?;
576         Ok(())
577     }
578 }
579 
580 struct Printer<'a, 'b: 'a, 's> {
581     parser: Result<Parser<'s>, Invalid>,
582     out: LimitedFormatter<'a, 'b>,
583     bound_lifetime_depth: u32,
584     depth: u32,
585 }
586 
587 /// Mark the parser as errored, print `?` and return early.
588 /// This allows callers to keep printing the approximate
589 /// syntax of the path/type/const, despite having errors.
590 /// E.g. `Vec<[(A, ?); ?]>` instead of `Vec<[(A, ?`.
591 macro_rules! invalid {
592     ($printer:ident) => {{
593         $printer.parser = Err(Invalid);
594         return $printer.out.write_str("?");
595     }};
596 }
597 
598 /// Call a parser method (if the parser hasn't errored yet),
599 /// and mark the parser as errored if it returns `Err(Invalid)`.
600 ///
601 /// If the parser errored, before or now, prints `?`, and
602 /// returns early the current function (see `invalid!` above).
603 macro_rules! parse {
604     ($printer:ident, $method:ident $(($($arg:expr),*))*) => {
605         match $printer.parser_mut().and_then(|p| p.$method($($($arg),*)*)) {
606             Ok(x) => x,
607             Err(Invalid) => invalid!($printer),
608         }
609     };
610 }
611 
612 impl<'a, 'b, 's> Printer<'a, 'b, 's> {
parser_mut<'c>(&'c mut self) -> Result<&'c mut Parser<'s>, Invalid>613     fn parser_mut<'c>(&'c mut self) -> Result<&'c mut Parser<'s>, Invalid> {
614         self.parser.as_mut().map_err(|_| Invalid)
615     }
616 
617     /// Eat the given character from the parser,
618     /// returning `false` if the parser errored.
eat(&mut self, b: u8) -> bool619     fn eat(&mut self, b: u8) -> bool {
620         self.parser_mut().map(|p| p.eat(b)) == Ok(true)
621     }
622 
bump_depth(&mut self) -> fmt::Result623     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 
632     /// Return a nested parser for a backref.
backref_printer<'c>(&'c mut self) -> Printer<'c, 'b, 's>633     fn backref_printer<'c>(&'c mut self) -> Printer<'c, 'b, 's> {
634         Printer {
635             parser: self.parser_mut().and_then(|p| p.backref()),
636             out: LimitedFormatter {
637                 remaining: self.out.remaining,
638                 inner: self.out.inner,
639             },
640             bound_lifetime_depth: self.bound_lifetime_depth,
641             depth: self.depth,
642         }
643     }
644 
645     /// Print the lifetime according to the previously decoded index.
646     /// An index of `0` always refers to `'_`, but starting with `1`,
647     /// indices refer to late-bound lifetimes introduced by a binder.
print_lifetime_from_index(&mut self, lt: u64) -> fmt::Result648     fn print_lifetime_from_index(&mut self, lt: u64) -> fmt::Result {
649         self.out.write_str("'")?;
650         if lt == 0 {
651             return self.out.write_str("_");
652         }
653         match (self.bound_lifetime_depth as u64).checked_sub(lt) {
654             Some(depth) => {
655                 // Try to print lifetimes alphabetically first.
656                 if depth < 26 {
657                     let c = (b'a' + depth as u8) as char;
658                     c.fmt(self.out.inner)
659                 } else {
660                     // Use `'_123` after running out of letters.
661                     self.out.write_str("_")?;
662                     depth.fmt(self.out.inner)
663                 }
664             }
665             None => invalid!(self),
666         }
667     }
668 
669     /// Optionally enter a binder ('G') for late-bound lifetimes,
670     /// printing e.g. `for<'a, 'b> ` before calling the closure,
671     /// and make those lifetimes visible to it (via depth level).
in_binder<F>(&mut self, f: F) -> fmt::Result where F: FnOnce(&mut Self) -> fmt::Result,672     fn in_binder<F>(&mut self, f: F) -> fmt::Result
673     where
674         F: FnOnce(&mut Self) -> fmt::Result,
675     {
676         let bound_lifetimes = parse!(self, opt_integer_62(b'G'));
677 
678         if bound_lifetimes > 0 {
679             self.out.write_str("for<")?;
680             for i in 0..bound_lifetimes {
681                 if i > 0 {
682                     self.out.write_str(", ")?;
683                 }
684                 self.bound_lifetime_depth += 1;
685                 self.print_lifetime_from_index(1)?;
686             }
687             self.out.write_str("> ")?;
688         }
689 
690         let r = f(self);
691 
692         // Restore `bound_lifetime_depth` to the previous value.
693         self.bound_lifetime_depth -= bound_lifetimes as u32;
694 
695         r
696     }
697 
698     /// Print list elements using the given closure and separator,
699     /// until the end of the list ('E') is found, or the parser errors.
700     /// Returns the number of elements printed.
print_sep_list<F>(&mut self, f: F, sep: &str) -> Result<usize, fmt::Error> where F: Fn(&mut Self) -> fmt::Result,701     fn print_sep_list<F>(&mut self, f: F, sep: &str) -> Result<usize, fmt::Error>
702     where
703         F: Fn(&mut Self) -> fmt::Result,
704     {
705         let mut i = 0;
706         while self.parser.is_ok() && !self.eat(b'E') {
707             if i > 0 {
708                 self.out.write_str(sep)?;
709             }
710             f(self)?;
711             i += 1;
712         }
713         Ok(i)
714     }
715 
print_path(&mut self, in_value: bool) -> fmt::Result716     fn print_path(&mut self, in_value: bool) -> fmt::Result {
717         self.bump_depth()?;
718         let tag = parse!(self, next);
719         match tag {
720             b'C' => {
721                 let dis = parse!(self, disambiguator);
722                 let name = parse!(self, ident);
723 
724                 name.fmt(self.out.inner)?;
725                 if !self.out.inner.alternate() {
726                     self.out.write_str("[")?;
727                     fmt::LowerHex::fmt(&dis, self.out.inner)?;
728                     self.out.write_str("]")?;
729                 }
730             }
731             b'N' => {
732                 let ns = parse!(self, namespace);
733 
734                 self.print_path(in_value)?;
735 
736                 let dis = parse!(self, disambiguator);
737                 let name = parse!(self, ident);
738 
739                 match ns {
740                     // Special namespaces, like closures and shims.
741                     Some(ns) => {
742                         self.out.write_str("::{")?;
743                         match ns {
744                             'C' => self.out.write_str("closure")?,
745                             'S' => self.out.write_str("shim")?,
746                             _ => ns.fmt(self.out.inner)?,
747                         }
748                         if !name.ascii.is_empty() || !name.punycode.is_empty() {
749                             self.out.write_str(":")?;
750                             name.fmt(self.out.inner)?;
751                         }
752                         self.out.write_str("#")?;
753                         dis.fmt(self.out.inner)?;
754                         self.out.write_str("}")?;
755                     }
756 
757                     // Implementation-specific/unspecified namespaces.
758                     None => {
759                         if !name.ascii.is_empty() || !name.punycode.is_empty() {
760                             self.out.write_str("::")?;
761                             name.fmt(self.out.inner)?;
762                         }
763                     }
764                 }
765             }
766             b'M' | b'X' | b'Y' => {
767                 if tag != b'Y' {
768                     // Ignore the `impl`'s own path.
769                     parse!(self, disambiguator);
770                     parse!(self, skip_path);
771                 }
772 
773                 self.out.write_str("<")?;
774                 self.print_type()?;
775                 if tag != b'M' {
776                     self.out.write_str(" as ")?;
777                     self.print_path(false)?;
778                 }
779                 self.out.write_str(">")?;
780             }
781             b'I' => {
782                 self.print_path(in_value)?;
783                 if in_value {
784                     self.out.write_str("::")?;
785                 }
786                 self.out.write_str("<")?;
787                 self.print_sep_list(Self::print_generic_arg, ", ")?;
788                 self.out.write_str(">")?;
789             }
790             b'B' => {
791                 self.backref_printer().print_path(in_value)?;
792             }
793             _ => invalid!(self),
794         }
795         self.depth -= 1;
796         Ok(())
797     }
798 
print_generic_arg(&mut self) -> fmt::Result799     fn print_generic_arg(&mut self) -> fmt::Result {
800         if self.eat(b'L') {
801             let lt = parse!(self, integer_62);
802             self.print_lifetime_from_index(lt)
803         } else if self.eat(b'K') {
804             self.print_const()
805         } else {
806             self.print_type()
807         }
808     }
809 
print_type(&mut self) -> fmt::Result810     fn print_type(&mut self) -> fmt::Result {
811         let tag = parse!(self, next);
812 
813         if let Some(ty) = basic_type(tag) {
814             return self.out.write_str(ty);
815         }
816 
817         self.bump_depth()?;
818         match tag {
819             b'R' | b'Q' => {
820                 self.out.write_str("&")?;
821                 if self.eat(b'L') {
822                     let lt = parse!(self, integer_62);
823                     if lt != 0 {
824                         self.print_lifetime_from_index(lt)?;
825                         self.out.write_str(" ")?;
826                     }
827                 }
828                 if tag != b'R' {
829                     self.out.write_str("mut ")?;
830                 }
831                 self.print_type()?;
832             }
833 
834             b'P' | b'O' => {
835                 self.out.write_str("*")?;
836                 if tag != b'P' {
837                     self.out.write_str("mut ")?;
838                 } else {
839                     self.out.write_str("const ")?;
840                 }
841                 self.print_type()?;
842             }
843 
844             b'A' | b'S' => {
845                 self.out.write_str("[")?;
846                 self.print_type()?;
847                 if tag == b'A' {
848                     self.out.write_str("; ")?;
849                     self.print_const()?;
850                 }
851                 self.out.write_str("]")?;
852             }
853             b'T' => {
854                 self.out.write_str("(")?;
855                 let count = self.print_sep_list(Self::print_type, ", ")?;
856                 if count == 1 {
857                     self.out.write_str(",")?;
858                 }
859                 self.out.write_str(")")?;
860             }
861             b'F' => self.in_binder(|this| {
862                 let is_unsafe = this.eat(b'U');
863                 let abi = if this.eat(b'K') {
864                     if this.eat(b'C') {
865                         Some("C")
866                     } else {
867                         let abi = parse!(this, ident);
868                         if abi.ascii.is_empty() || !abi.punycode.is_empty() {
869                             invalid!(this);
870                         }
871                         Some(abi.ascii)
872                     }
873                 } else {
874                     None
875                 };
876 
877                 if is_unsafe {
878                     this.out.write_str("unsafe ")?;
879                 }
880 
881                 if let Some(abi) = abi {
882                     this.out.write_str("extern \"")?;
883 
884                     // If the ABI had any `-`, they were replaced with `_`,
885                     // so the parts between `_` have to be re-joined with `-`.
886                     let mut parts = abi.split('_');
887                     this.out.write_str(parts.next().unwrap())?;
888                     for part in parts {
889                         this.out.write_str("-")?;
890                         this.out.write_str(part)?;
891                     }
892 
893                     this.out.write_str("\" ")?;
894                 }
895 
896                 this.out.write_str("fn(")?;
897                 this.print_sep_list(Self::print_type, ", ")?;
898                 this.out.write_str(")")?;
899 
900                 if this.eat(b'u') {
901                     // Skip printing the return type if it's 'u', i.e. `()`.
902                 } else {
903                     this.out.write_str(" -> ")?;
904                     this.print_type()?;
905                 }
906 
907                 Ok(())
908             })?,
909             b'D' => {
910                 self.out.write_str("dyn ")?;
911                 self.in_binder(|this| {
912                     this.print_sep_list(Self::print_dyn_trait, " + ")?;
913                     Ok(())
914                 })?;
915 
916                 if !self.eat(b'L') {
917                     invalid!(self);
918                 }
919                 let lt = parse!(self, integer_62);
920                 if lt != 0 {
921                     self.out.write_str(" + ")?;
922                     self.print_lifetime_from_index(lt)?;
923                 }
924             }
925             b'B' => {
926                 self.backref_printer().print_type()?;
927             }
928             _ => {
929                 // Go back to the tag, so `print_path` also sees it.
930                 let _ = self.parser_mut().map(|p| p.next -= 1);
931                 self.print_path(false)?;
932             }
933         }
934         self.depth -= 1;
935         Ok(())
936     }
937 
938     /// A trait in a trait object may have some "existential projections"
939     /// (i.e. associated type bindings) after it, which should be printed
940     /// in the `<...>` of the trait, e.g. `dyn Trait<T, U, Assoc=X>`.
941     /// To this end, this method will keep the `<...>` of an 'I' path
942     /// open, by omitting the `>`, and return `Ok(true)` in that case.
print_path_maybe_open_generics(&mut self) -> Result<bool, fmt::Error>943     fn print_path_maybe_open_generics(&mut self) -> Result<bool, fmt::Error> {
944         if self.eat(b'B') {
945             self.backref_printer().print_path_maybe_open_generics()
946         } else if self.eat(b'I') {
947             self.print_path(false)?;
948             self.out.write_str("<")?;
949             self.print_sep_list(Self::print_generic_arg, ", ")?;
950             Ok(true)
951         } else {
952             self.print_path(false)?;
953             Ok(false)
954         }
955     }
956 
print_dyn_trait(&mut self) -> fmt::Result957     fn print_dyn_trait(&mut self) -> fmt::Result {
958         let mut open = self.print_path_maybe_open_generics()?;
959 
960         while self.eat(b'p') {
961             if !open {
962                 self.out.write_str("<")?;
963                 open = true;
964             } else {
965                 self.out.write_str(", ")?;
966             }
967 
968             let name = parse!(self, ident);
969             name.fmt(self.out.inner)?;
970             self.out.write_str(" = ")?;
971             self.print_type()?;
972         }
973 
974         if open {
975             self.out.write_str(">")?;
976         }
977 
978         Ok(())
979     }
980 
print_const(&mut self) -> fmt::Result981     fn print_const(&mut self) -> fmt::Result {
982         if self.eat(b'B') {
983             return self.backref_printer().print_const();
984         }
985 
986         let ty_tag = parse!(self, next);
987 
988         if ty_tag == b'p' {
989             // We don't encode the type if the value is a placeholder.
990             self.out.write_str("_")?;
991             return Ok(());
992         }
993 
994         match ty_tag {
995             // Unsigned integer types.
996             b'h' | b't' | b'm' | b'y' | b'o' | b'j' => self.print_const_uint()?,
997             // Signed integer types.
998             b'a' | b's' | b'l' | b'x' | b'n' | b'i' => self.print_const_int()?,
999             // Bool.
1000             b'b' => self.print_const_bool()?,
1001             // Char.
1002             b'c' => self.print_const_char()?,
1003 
1004             // This branch ought to be unreachable.
1005             _ => invalid!(self),
1006         };
1007 
1008         if !self.out.inner.alternate() {
1009             self.out.write_str(": ")?;
1010             let ty = basic_type(ty_tag).unwrap();
1011             self.out.write_str(ty)?;
1012         }
1013 
1014         Ok(())
1015     }
1016 
print_const_uint(&mut self) -> fmt::Result1017     fn print_const_uint(&mut self) -> fmt::Result {
1018         let hex = parse!(self, hex_nibbles);
1019 
1020         // Print anything that doesn't fit in `u64` verbatim.
1021         if hex.len() > 16 {
1022             self.out.write_str("0x")?;
1023             return self.out.write_str(hex);
1024         }
1025 
1026         let mut v = 0;
1027         for c in hex.chars() {
1028             v = (v << 4) | (c.to_digit(16).unwrap() as u64);
1029         }
1030         v.fmt(self.out.inner)
1031     }
1032 
print_const_int(&mut self) -> fmt::Result1033     fn print_const_int(&mut self) -> fmt::Result {
1034         if self.eat(b'n') {
1035             self.out.write_str("-")?;
1036         }
1037 
1038         self.print_const_uint()
1039     }
1040 
print_const_bool(&mut self) -> fmt::Result1041     fn print_const_bool(&mut self) -> fmt::Result {
1042         match parse!(self, hex_nibbles).as_bytes() {
1043             b"0" => self.out.write_str("false"),
1044             b"1" => self.out.write_str("true"),
1045             _ => invalid!(self),
1046         }
1047     }
1048 
print_const_char(&mut self) -> fmt::Result1049     fn print_const_char(&mut self) -> fmt::Result {
1050         let hex = parse!(self, hex_nibbles);
1051 
1052         // Valid `char`s fit in `u32`.
1053         if hex.len() > 8 {
1054             invalid!(self);
1055         }
1056 
1057         let mut v = 0;
1058         for c in hex.chars() {
1059             v = (v << 4) | (c.to_digit(16).unwrap() as u32);
1060         }
1061         if let Some(c) = char::from_u32(v) {
1062             write!(self.out, "{:?}", c)
1063         } else {
1064             invalid!(self)
1065         }
1066     }
1067 }
1068 
1069 #[cfg(test)]
1070 mod tests {
1071     macro_rules! t_nohash {
1072         ($a:expr, $b:expr) => {{
1073             assert_eq!(format!("{:#}", ::demangle($a)), $b);
1074         }};
1075     }
1076     macro_rules! t_nohash_type {
1077         ($a:expr, $b:expr) => {
1078             t_nohash!(concat!("_RMC0", $a), concat!("<", $b, ">"))
1079         };
1080     }
1081 
1082     #[test]
demangle_crate_with_leading_digit()1083     fn demangle_crate_with_leading_digit() {
1084         t_nohash!("_RNvC6_123foo3bar", "123foo::bar");
1085     }
1086 
1087     #[test]
demangle_utf8_idents()1088     fn demangle_utf8_idents() {
1089         t_nohash!(
1090             "_RNqCs4fqI2P2rA04_11utf8_identsu30____7hkackfecea1cbdathfdh9hlq6y",
1091             "utf8_idents::საჭმელად_გემრიელი_სადილი"
1092         );
1093     }
1094 
1095     #[test]
demangle_closure()1096     fn demangle_closure() {
1097         t_nohash!(
1098             "_RNCNCNgCs6DXkGYLi8lr_2cc5spawn00B5_",
1099             "cc::spawn::{closure#0}::{closure#0}"
1100         );
1101         t_nohash!(
1102             "_RNCINkXs25_NgCsbmNqQUJIY6D_4core5sliceINyB9_4IterhENuNgNoBb_4iter8iterator8Iterator9rpositionNCNgNpB9_6memchr7memrchrs_0E0Bb_",
1103             "<core::slice::Iter<u8> as core::iter::iterator::Iterator>::rposition::<core::slice::memchr::memrchr::{closure#1}>::{closure#0}"
1104         );
1105     }
1106 
1107     #[test]
demangle_dyn_trait()1108     fn demangle_dyn_trait() {
1109         t_nohash!(
1110             "_RINbNbCskIICzLVDPPb_5alloc5alloc8box_freeDINbNiB4_5boxed5FnBoxuEp6OutputuEL_ECs1iopQbuBiw2_3std",
1111             "alloc::alloc::box_free::<dyn alloc::boxed::FnBox<(), Output = ()>>"
1112         );
1113     }
1114 
1115     #[test]
demangle_const_generics()1116     fn demangle_const_generics() {
1117         // NOTE(eddyb) this was hand-written, before rustc had working
1118         // const generics support (but the mangling format did include them).
1119         t_nohash_type!(
1120             "INtC8arrayvec8ArrayVechKj7b_E",
1121             "arrayvec::ArrayVec<u8, 123>"
1122         );
1123         t_nohash!(
1124             "_RMCs4fqI2P2rA04_13const_genericINtB0_8UnsignedKhb_E",
1125             "<const_generic::Unsigned<11>>"
1126         );
1127         t_nohash!(
1128             "_RMCs4fqI2P2rA04_13const_genericINtB0_6SignedKs98_E",
1129             "<const_generic::Signed<152>>"
1130         );
1131         t_nohash!(
1132             "_RMCs4fqI2P2rA04_13const_genericINtB0_6SignedKanb_E",
1133             "<const_generic::Signed<-11>>"
1134         );
1135         t_nohash!(
1136             "_RMCs4fqI2P2rA04_13const_genericINtB0_4BoolKb0_E",
1137             "<const_generic::Bool<false>>"
1138         );
1139         t_nohash!(
1140             "_RMCs4fqI2P2rA04_13const_genericINtB0_4BoolKb1_E",
1141             "<const_generic::Bool<true>>"
1142         );
1143         t_nohash!(
1144             "_RMCs4fqI2P2rA04_13const_genericINtB0_4CharKc76_E",
1145             "<const_generic::Char<'v'>>"
1146         );
1147         t_nohash!(
1148             "_RMCs4fqI2P2rA04_13const_genericINtB0_4CharKca_E",
1149             "<const_generic::Char<'\\n'>>"
1150         );
1151         t_nohash!(
1152             "_RMCs4fqI2P2rA04_13const_genericINtB0_4CharKc2202_E",
1153             "<const_generic::Char<'∂'>>"
1154         );
1155         t_nohash!(
1156             "_RNvNvMCs4fqI2P2rA04_13const_genericINtB4_3FooKpE3foo3FOO",
1157             "<const_generic::Foo<_>>::foo::FOO"
1158         );
1159     }
1160 
1161     #[test]
demangle_exponential_explosion()1162     fn demangle_exponential_explosion() {
1163         // NOTE(eddyb) because of the prefix added by `t_nohash_type!` is
1164         // 3 bytes long, `B2_` refers to the start of the type, not `B_`.
1165         // 6 backrefs (`B8_E` through `B3_E`) result in 2^6 = 64 copies of `_`.
1166         // Also, because the `p` (`_`) type is after all of the starts of the
1167         // backrefs, it can be replaced with any other type, independently.
1168         t_nohash_type!(
1169             concat!("TTTTTT", "p", "B8_E", "B7_E", "B6_E", "B5_E", "B4_E", "B3_E"),
1170             "((((((_, _), (_, _)), ((_, _), (_, _))), (((_, _), (_, _)), ((_, _), (_, _)))), \
1171              ((((_, _), (_, _)), ((_, _), (_, _))), (((_, _), (_, _)), ((_, _), (_, _))))), \
1172              (((((_, _), (_, _)), ((_, _), (_, _))), (((_, _), (_, _)), ((_, _), (_, _)))), \
1173              ((((_, _), (_, _)), ((_, _), (_, _))), (((_, _), (_, _)), ((_, _), (_, _))))))"
1174         );
1175     }
1176 
1177     #[test]
demangle_thinlto()1178     fn demangle_thinlto() {
1179         t_nohash!("_RC3foo.llvm.9D1C9369", "foo");
1180         t_nohash!("_RC3foo.llvm.9D1C9369@@16", "foo");
1181         t_nohash!("_RNvC9backtrace3foo.llvm.A5310EB9", "backtrace::foo");
1182     }
1183 
1184     #[test]
demangle_extra_suffix()1185     fn demangle_extra_suffix() {
1186         // From alexcrichton/rustc-demangle#27:
1187         t_nohash!(
1188             "_RNvNtNtNtNtCs92dm3009vxr_4rand4rngs7adapter9reseeding4fork23FORK_HANDLER_REGISTERED.0.0",
1189             "rand::rngs::adapter::reseeding::fork::FORK_HANDLER_REGISTERED.0.0"
1190         );
1191     }
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<'_, '_> {
write_str(&mut self, s: &str) -> fmt::Result1200     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 }
1210