I'd like to write a safe Rust wrapper for a C library. I need to express the C's library raw pointer ownership rules in Rust's terms.
The library has its private structure such as: struct handle {void *_data}
and exposes setter as set_data(struct handle*, void *data)
.
I'd like to make Rust version of that method with signature that says "data
must live at least as long as the handle
".
I've tried:
set_data(&'a self, &'a data:…)
but borrow checker seems to apply that to lifetime within that function, not overall lifetime of the object.
I've also tried to add lifetime to impl
, but that's still no good. Full test case:
#![allow(unused_variables)]
struct Handle<'a>;
impl<'a> Handle<'a> {
pub fn set_data(&'a mut self, data: &'a DropCanary) {
// save data raw ptr
}
pub fn use_data(&'a self) {
// use data raw ptr
println!("alive?");
}
}
fn main() {
let mut handle = Handle;
let long_enough_lifetime = DropCanary{label:"long"};
{
let short_lifetime = DropCanary{label:"short"};
handle.set_data(&short_lifetime); // This shouldn't be allowed!
handle.set_data(&long_enough_lifetime); // This is OK
}
handle.use_data();
}
/// --- just for testing ---
struct DropCanary {
label: &'static str,
}
impl Drop for DropCanary {
fn drop(&mut self) {
println!("dropped: {}", self.label);
}
}
The problem is that the following code compiles and outputs:
dropped: short
alive?
dropped: long
So it causes use-after-free, because Rust doesn't know that short_lifetime
must outlive handle
.