Search code examples
rustborrow-checker

cannot return value referencing local data


I'm new to rust. The get_x509 function below creates a compiler warning "cannot return value referencing local data pem.contents" . I think I understand why - because the return value references pem.contents which is only in scope for that function - but I've not been able to work out how to get it to work.

The x509 functions in the code below come from the x509_parser crate

use x509_parser::prelude::*;

fn main() {
    let cert = "";
    get_x509(cert);
}

fn get_x509(cert: &str) -> X509Certificate {
    let res_pem = parse_x509_pem(cert.as_bytes());
    let x509_cert = match res_pem {
        Ok((_, pem)) => {
            let res_cert = parse_x509_certificate(&pem.contents);
            match res_cert {
                Ok((_, certificate)) => certificate,
                Err(_err) => {
                    panic!("Parse failed")
                }
            }
        }
        Err(_err) => {
            panic!("Parse failed")
        }
    };
    return x509_cert;
}

I've tried making the cert variable a static value. If I inline the above code in the main() function, it works (but I have to match on &res_pem instead of res_pem).


Solution

  • According to x509-parser-0.14.0/src/certificate.rs, both the parameter and the return value of parse_x509_certificate have a lifetime 'a associated with them. One way to solve the problem is to divide get_x509 into two functions, and you can somehow avoid local reference in the second function which calls parse_x509_certificate.

    The following code compiles (but will panic at runtime since cert is empty):

    fn main() {
        let cert = "";
        let pem = get_x509_pem(cert);
        get_x509(&pem); // Return value is unused.
    }
    
    use x509_parser::prelude::*;
    
    fn get_x509_pem(cert: &str) -> Pem {
        let (_, pem) = parse_x509_pem(cert.as_bytes()).expect("Parse failed");
        pem
    }
    
    fn get_x509(pem: &Pem) -> X509Certificate {
        let x509_cert = match parse_x509_certificate(&pem.contents) {
            Ok((_, certificate)) => certificate,
            Err(_err) => {
                panic!("Parse failed")
            }
        };
        x509_cert
    }