v0: don't ignore recursion limit failures from any `push_depth` calls. (#52)

diff --git a/src/lib.rs b/src/lib.rs
index 775ad12..64c30ad 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -418,9 +418,17 @@
 
     #[test]
     fn limit_recursion() {
-        use std::fmt::Write;
-        let mut s = String::new();
-        assert!(write!(s, "{}", super::demangle("_RNvB_1a")).is_err());
+        // NOTE(eddyb) the `?` indicate that a parse error was encountered.
+        // FIXME(eddyb) replace `v0::Invalid` with a proper `v0::ParseError`,
+        // that could show e.g. `<recursion limit reached>` instead of `?`.
+        assert_eq!(
+            super::demangle("_RNvB_1a").to_string().replace("::a", ""),
+            "?"
+        );
+        assert_eq!(
+            super::demangle("_RMC0RB2_").to_string().replace("&", ""),
+            "<?>"
+        );
     }
 
     #[test]
diff --git a/src/v0.rs b/src/v0.rs
index bc2f9b6..b07f182 100644
--- a/src/v0.rs
+++ b/src/v0.rs
@@ -568,6 +568,8 @@
 
         if self.eat(b'B') {
             self.backref()?;
+
+            self.pop_depth();
             return Ok(());
         }
 
@@ -575,6 +577,7 @@
 
         if ty_tag == b'p' {
             // We don't encode the type if the value is a placeholder.
+            self.pop_depth();
             return Ok(());
         }
 
@@ -653,16 +656,6 @@
         }
     }
 
-    fn push_depth(&mut self) -> bool {
-        match self.parser {
-            Err(_) => false,
-            Ok(ref mut parser) => {
-                let _ = parser.push_depth();
-                true
-            }
-        }
-    }
-
     fn pop_depth(&mut self) {
         if let Ok(ref mut parser) = self.parser {
             parser.pop_depth();
@@ -740,6 +733,8 @@
     }
 
     fn print_path(&mut self, in_value: bool) -> fmt::Result {
+        parse!(self, push_depth);
+
         let tag = parse!(self, next);
         match tag {
             b'C' => {
@@ -813,14 +808,12 @@
                 self.out.write_str(">")?;
             }
             b'B' => {
-                let mut backref_printer = self.backref_printer();
-                backref_printer.print_path(in_value)?;
-                if backref_printer.parser.is_err() {
-                    return Err(fmt::Error);
-                }
+                self.backref_printer().print_path(in_value)?;
             }
             _ => invalid!(self),
         }
+
+        self.pop_depth();
         Ok(())
     }
 
@@ -842,7 +835,7 @@
             return self.out.write_str(ty);
         }
 
-        self.push_depth();
+        parse!(self, push_depth);
 
         match tag {
             b'R' | b'Q' => {
@@ -1009,8 +1002,13 @@
     }
 
     fn print_const(&mut self) -> fmt::Result {
+        parse!(self, push_depth);
+
         if self.eat(b'B') {
-            return self.backref_printer().print_const();
+            self.backref_printer().print_const()?;
+
+            self.pop_depth();
+            return Ok(());
         }
 
         let ty_tag = parse!(self, next);
@@ -1018,6 +1016,8 @@
         if ty_tag == b'p' {
             // We don't encode the type if the value is a placeholder.
             self.out.write_str("_")?;
+
+            self.pop_depth();
             return Ok(());
         }
 
@@ -1041,6 +1041,7 @@
             self.out.write_str(ty)?;
         }
 
+        self.pop_depth();
         Ok(())
     }
 
@@ -1810,4 +1811,37 @@
             t_nohash!(&sym, expected);
         }
     }
+
+    #[test]
+    fn recursion_limit_backref_free_bypass() {
+        // NOTE(eddyb) this test checks that long symbols cannot bypass the
+        // recursion limit by not using backrefs, and cause a stack overflow.
+
+        // This value was chosen to be high enough that stack overflows were
+        // observed even with `cargo test --release`.
+        let depth = 100_000;
+
+        // In order to hide the long mangling from the initial "shallow" parse,
+        // it's nested in an identifier (crate name), preceding its use.
+        let mut sym = format!("_RIC{}", depth);
+        let backref_start = sym.len() - 2;
+        for _ in 0..depth {
+            sym.push('R');
+        }
+
+        // Write a backref to just after the length of the identifier.
+        sym.push('B');
+        sym.push(char::from_digit((backref_start - 1) as u32, 36).unwrap());
+        sym.push('_');
+
+        // Close the `I` at the start.
+        sym.push('E');
+
+        let demangled = format!("{:#}", ::demangle(&sym));
+
+        // NOTE(eddyb) the `?` indicates that a parse error was encountered.
+        // FIXME(eddyb) replace `v0::Invalid` with a proper `v0::ParseError`,
+        // that could show e.g. `<recursion limit reached>` instead of `?`.
+        assert_eq!(demangled.replace(&['R', '&'][..], ""), "::<?>");
+    }
 }