Fix some panics uncovered via fuzzing

Closes #9
diff --git a/src/lib.rs b/src/lib.rs
index 3a8e905..9610077 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -117,22 +117,36 @@
         valid = false;
     }
 
+    // only work with ascii text
+    if inner.bytes().any(|c| c & 0x80 != 0) {
+        valid = false;
+    }
+
     let mut elements = 0;
     if valid {
-        let mut chars = inner.chars();
+        let mut chars = inner.chars().peekable();
         while valid {
-            let mut i = 0;
-            for c in chars.by_ref() {
-                if c.is_digit(10) {
-                    i = i * 10 + c as usize - '0' as usize;
-                } else {
-                    break;
+            let mut i = 0usize;
+            while let Some(&c) = chars.peek() {
+                if !c.is_digit(10) {
+                    break
                 }
+                chars.next();
+                let next = i.checked_mul(10)
+                    .and_then(|i| i.checked_add(c as usize - '0' as usize));
+                i = match next {
+                    Some(i) => i,
+                    None => {
+                        valid = false;
+                        break
+                    }
+                };
             }
+
             if i == 0 {
                 valid = chars.next().is_none();
                 break;
-            } else if chars.by_ref().take(i - 1).count() != i - 1 {
+            } else if chars.by_ref().take(i).count() != i {
                 valid = false;
             } else {
                 elements += 1;
@@ -383,4 +397,16 @@
         t!("_ZN3fooE.llvm.9D1C9369", "foo");
         t_nohash!("_ZN9backtrace3foo17hbb467fcdaea5d79bE.llvm.A5310EB9", "backtrace::foo");
     }
+
+    #[test]
+    fn dont_panic() {
+        super::demangle("_ZN2222222222222222222222EE").to_string();
+        super::demangle("_ZN5*70527e27.ll34csaғE").to_string();
+        super::demangle("_ZN5*70527a54.ll34_$b.1E").to_string();
+        super::demangle("\
+            _ZN5~saäb4e\n\
+            2734cOsbE\n\
+            5usage20h)3\0\0\0\0\0\0\07e2734cOsbE\
+        ").to_string();
+    }
 }