Repository: alex/rust-asn1 (language: rust)

Issue:
Crash found by AFL
test case

``` rust
    #[test]
    fn test_fuzz() {
        assert_deserializes(vec![
            (Err(DeserializationError::InvalidValue), b"\x30\x86\xcd\x98\x81\xcd\xcd\x0a\xcd\x0a".to_vec())
        ], |deserializer| {
            return deserializer.read_sequence(|d| {
                Ok((try!(d.read_int::<i64>()),
                    try!(d.read_octet_string()),
                    try!(d.read_object_identifier()),
                    try!(d.read_bool())))
            });
        });
    }
```

run test

```
coreyf@frewbook-pro ~/D/r/rust-asn1 (master) [101]> cargo test test_fuzz
     Running target/debug/asn1-7ff997e9ea245d04

running 1 test
Process didn't exit successfully: `/Users/coreyf/Development/rust/rust-asn1/target/debug/asn1-7ff997e9ea245d04 test_fuzz` (signal: 4)
```

lldb backtrace

```
coreyf@frewbook-pro ~/D/r/rust-asn1 (master) [127]>
lldb /Users/coreyf/Development/rust/rust-asn1/target/debug/asn1-7ff997e9ea245d04 test_fuzz
(lldb) target create "/Users/coreyf/Development/rust/rust-asn1/target/debug/asn1-7ff997e9ea245d04"
Current executable set to '/Users/coreyf/Development/rust/rust-asn1/target/debug/asn1-7ff997e9ea245d04' (x86_64).
(lldb) settings set -- target.run-args  "test_fuzz"
(lldb) run
Process 78929 launched: '/Users/coreyf/Development/rust/rust-asn1/target/debug/asn1-7ff997e9ea245d04' (x86_64)

running 1 test
Process 78929 stopped
* thread #2: tid = 0x264423, 0x00000001000ac004 asn1-7ff997e9ea245d04`oom::h60a2387de2f8f1f2fub + 4, name = 'deserializer::tests::test_fuzz', stop reason = EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
    frame #0: 0x00000001000ac004 asn1-7ff997e9ea245d04`oom::h60a2387de2f8f1f2fub + 4
asn1-7ff997e9ea245d04`oom::h60a2387de2f8f1f2fub:
->  0x1000ac004 <+4>: ud2
    0x1000ac006 <+6>: nopw   %cs:(%rax,%rax)

asn1-7ff997e9ea245d04`__rust_allocate:
    0x1000ac010 <+0>: pushq  %rbp
    0x1000ac011 <+1>: movq   %rsp, %rbp
(lldb) bt
* thread #2: tid = 0x264423, 0x00000001000ac004 asn1-7ff997e9ea245d04`oom::h60a2387de2f8f1f2fub + 4, name = 'deserializer::tests::test_fuzz', stop reason = EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
  * frame #0: 0x00000001000ac004 asn1-7ff997e9ea245d04`oom::h60a2387de2f8f1f2fub + 4
    frame #1: 0x0000000100004abc asn1-7ff997e9ea245d04`asn1::raw_vec::RawVec<T>::with_capacity(cap=226054896471306) + 156 at raw_vec.rs:103
    frame #2: 0x0000000100004a00 asn1-7ff997e9ea245d04`asn1::vec::Vec<T>::with_capacity(capacity=226054896471306) + 32 at vec.rs:282
    frame #3: 0x0000000100004950 asn1-7ff997e9ea245d04`asn1::vec::from_elem<u8>(elem='\0', n=226054896471306) + 48 at vec.rs:1058
    frame #4: 0x000000010002863f asn1-7ff997e9ea245d04`asn1::deserializer::Deserializer::_read_with_tag<(i64, collections::vec::Vec<u8>, asn1::utils::ObjectIdentifier, bool),closure>(self=0x0000700000403828, expected_tag='0', body=(__0 = 0x0000700000403590)) + 703 at deserializer.rs:92
    frame #5: 0x000000010002834d asn1-7ff997e9ea245d04`asn1::deserializer::Deserializer::read_sequence<closure,(i64, collections::vec::Vec<u8>, asn1::utils::ObjectIdentifier, bool)>(self=0x0000700000403828, v=closure @ 0x0000700000403590) + 77 at deserializer.rs:164
    frame #6: 0x0000000100027760 asn1-7ff997e9ea245d04`fnfn(deserializer=0x0000700000403828) + 64 at deserializer.rs:378
    frame #7: 0x0000000100027707 asn1-7ff997e9ea245d04`asn1::ops::impls::&'a F.Fn<A>::call(self=0x0000700000403848, args=(&mut asn1::deserializer::Deserializer) @ 0x0000700000403690) + 39 at ops.rs:1760
    frame #8: 0x000000010002735b asn1-7ff997e9ea245d04`asn1::deserializer::from_vec<&closure,(i64, collections::vec::Vec<u8>, asn1::utils::ObjectIdentifier, bool)>(data=Vec<u8> @ 0x0000700000403850, f=0x0000700000403ae0) + 171 at deserializer.rs:173
    frame #9: 0x0000000100025f3c asn1-7ff997e9ea245d04`asn1::deserializer::tests::assert_deserializes<(i64, collections::vec::Vec<u8>, asn1::utils::ObjectIdentifier, bool),closure>(values=Vec<(core::result::Result<(i64, collections::vec::Vec<u8>, asn1::utils::ObjectIdentifier, bool), asn1::deserializer::DeserializationError>, collections::vec::Vec<u8>)> @ 0x0000700000403ae8, f=closure @ 0x0000700000403ae0) + 492 at deserializer.rs:191
    frame #10: 0x0000000100025cfb asn1-7ff997e9ea245d04`asn1::deserializer::tests::test_fuzz + 347 at deserializer.rs:375
    frame #11: 0x000000010008226c asn1-7ff997e9ea245d04`boxed::_$LT$impl$GT$::call_box::call_box::h13072048137075833162 + 28
    frame #12: 0x0000000100084971 asn1-7ff997e9ea245d04`sys_common::unwind::try::try_fn::try_fn::h751026771818371460 + 433
    frame #13: 0x00000001000a7929 asn1-7ff997e9ea245d04`__rust_try + 9
    frame #14: 0x00000001000a58cf asn1-7ff997e9ea245d04`sys_common::unwind::try::inner_try::h2088a2c04cd75530O7r + 111
    frame #15: 0x0000000100084d6b asn1-7ff997e9ea245d04`boxed::_$LT$impl$GT$::call_box::call_box::h9872188538580151393 + 411
    frame #16: 0x00000001000a92fe asn1-7ff997e9ea245d04`sys::thread::_$LT$impl$GT$::new::thread_start::h72c909587b43bc6f8tw + 142
    frame #17: 0x00007fff94c049b1 libsystem_pthread.dylib`_pthread_body + 131
    frame #18: 0x00007fff94c0492e libsystem_pthread.dylib`_pthread_start + 168
    frame #19: 0x00007fff94c02385 libsystem_pthread.dylib`thread_start + 13
```



Discussion / hints:

Fix patch:
diff --git a/src/deserializer.rs b/src/deserializer.rs
index 521666e..829167b 100644
--- a/src/deserializer.rs
+++ b/src/deserializer.rs
@@ -89,11 +89,14 @@ impl Deserializer {
             return Err(DeserializationError::UnexpectedTag);
         }
         let length = try!(self._read_length());
-        let mut data = vec![0; length];
-        let n = self.reader.read(&mut data).unwrap();
-        if n != length {
+        // Check for short data before allocating the data Vec so we disallow obscenely large
+        // lengths
+        if length > (self.reader.get_ref().len() - self.reader.position() as usize) {
             return Err(DeserializationError::ShortData);
         }
+        let mut data = vec![0; length];
+        let n = self.reader.read(&mut data).unwrap();
+        assert_eq!(n, length);
         return body(data);
     }
 
@@ -314,6 +317,7 @@ mod tests {
                 b"\x04\x89\x01\x01\x01\x01\x01\x01\x01\x01\x01".to_vec()
             ),
             (Err(DeserializationError::ShortData), b"\x04\x03\x01\x02".to_vec()),
+            (Err(DeserializationError::ShortData), b"\x04\x86\xff\xff\xff\xff\xff\xff".to_vec()),
         ], |deserializer| {
             return deserializer.read_octet_string();
         });


Test patch: