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();
+ }
}