Reputation: 3
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).
Upvotes: 0
Views: 252
Reputation: 115
The issue here, just as you've said, is that you have something that only lives in the context of the function, and you want to return a reference to it (or to some parts of it). But when the function execution is finished, the underlying data is removed, hence you would return a dangling reference - and Rust prevents this.
The way to go around this is (well illustrated by the answer of Simon Smith) to return the data you'd like to reference instead of just returning the reference. So in your case, you want to return the whole resp_pem
object and then do any further data extraction.
Reading the documentation of the library, you seem to be in an unlucky situation where there is no way around moving res_pem
out of the function into a static space, since parse_x509_pem
returns owned data, and X509Certificate
contains references. Hence, the lifetime of the returned certificate has to outlive the function, but the object you reference (res_pem
) is owned by the function and is removed when the execution of the function is finished.
Upvotes: 0
Reputation: 472
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
}
Upvotes: 0