rusticata / der-parser

BER/DER parser written in pure Rust. Fast, zero-copy, safe.
Apache License 2.0
85 stars 28 forks source link

tagged: fix lifetime on BerObjectHeader #30

Closed cccs-sadugas closed 4 years ago

cccs-sadugas commented 4 years ago

The lifetime for BerObjectHeader<'hdr> was elided so it was not bound to 'a. However, it is clear that the BerObjectHeader<'hdr> should be bound to the input that it is parsing.

This was generating a strange compiler warning for me as shown below.

Lifetime elision rules can be found here:

Steps to reproduce (roughly):

fn parse_tag_0_implicit_octectstring(input: &[u8]) -> BerResult {
    parse_ber_tagged_implicit(0, |input, header, rec| {
        // unwrapping for simplicity
        let (input, content) = parse_ber_content(BerTag::OctetString)(input, &header, rec).unwrap();
        // deref will cause a clone
        let obj = BerObject::from_header_and_content(*header, content);
        Ok((input, obj))
    })(input)
}

Full error message:

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter 'hdr in function call due to conflicting requirements
  --> foo/src/lib.rs:9:19
   |
9  |         let obj = BerObject::from_header_and_content(*header, content);
   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #3 defined on the body at 7:34...
  --> foo/src/lib.rs:7:34
   |
7  |       parse_ber_tagged_implicit(0, |input, header, rec| {
   |  __________________________________^
8  | |         let (input, content) = parse_ber_content(BerTag::OctetString)(input, &header, rec).unwrap();
9  | |         let obj = BerObject::from_header_and_content(*header, content);
10 | |         Ok((input, obj))
11 | |     })(input)
   | |_____^
note: ...so that the expression is assignable
  --> foo/src/lib.rs:9:54
   |
9  |         let obj = BerObject::from_header_and_content(*header, content);
   |                                                      ^^^^^^^
   = note: expected `der_parser::ber::BerObjectHeader<'_>`
              found `der_parser::ber::BerObjectHeader<'_>`
note: but, the lifetime must be valid for the anonymous lifetime #1 defined on the function body at 6:1...
  --> foo/src/lib.rs:6:1
   |
6  | / fn parse_tag_0_implicit_octectstring(input: &[u8]) -> BerResult {
7  | |     parse_ber_tagged_implicit(0, |input, header, rec| {
8  | |         let (input, content) = parse_ber_content(BerTag::OctetString)(input, &header, rec).unwrap();
9  | |         let obj = BerObject::from_header_and_content(*header, content);
10 | |         Ok((input, obj))
11 | |     })(input)
12 | | }
   | |_^
note: ...so that the expression is assignable
  --> foo/src/lib.rs:7:5
   |
7  | /     parse_ber_tagged_implicit(0, |input, header, rec| {
8  | |         let (input, content) = parse_ber_content(BerTag::OctetString)(input, &header, rec).unwrap();
9  | |         let obj = BerObject::from_header_and_content(*header, content);
10 | |         Ok((input, obj))
11 | |     })(input)
   | |_____________^
   = note: expected `std::result::Result<(&[u8], der_parser::ber::BerObject<'_>), _>`
              found `std::result::Result<(&[u8], der_parser::ber::BerObject<'_>), _>`

error: aborting due to previous error; 1 warning emitted

For more information about this error, try `rustc --explain E0495`.
error: could not compile `foo`.
chifflier commented 4 years ago

Thanks for the detailed issue, with example and fix. Applied! I will also backport the fix for 4.x