A wrapper is created around bumpalo allocator to side step the issue of annotating everything that has to be allocated on the allocator with a lifetime. A guard was created with the idea to clean up the allocator when the guard is dropped.
thread_local! {
static CURRENT_ALLOCATOR: Cell<Option<&'static WrapAllocator>> = const { Cell::new(None) };
}
pub struct WrapAllocator {
bump: Bump,
}
#[derive(Clone, Copy)]
pub struct LimboAllocator {
allocator: Option<&'static WrapAllocator>,
}
pub struct AllocatorGuard {}
impl Drop for AllocatorGuard {
fn drop(&mut self) {
println!("dropping!!!");
CURRENT_ALLOCATOR.set(None);
}
}
impl WrapAllocator {
pub fn new() -> Self {
println!("new allocator!!!");
Self { bump: Bump::new() }
}
pub unsafe fn guard(&self) -> AllocatorGuard {
let static_ref = unsafe { transmute::<&WrapAllocator, &'static WrapAllocator>(self) };
CURRENT_ALLOCATOR.set(Some(static_ref));
AllocatorGuard {}
}
}
And when I tried to use this with a parser miri throws a UB error that has use after free.
This minimal example that reproduces the parser and allocator interaction:
struct TestParser<'a> {
some_reference: &'a str,
vector: Vec<String>,
_allocator: WrapAllocator,
_guard: AllocatorGuard,
}
impl<'a> TestParser<'a> {
fn new(reference: &'a str) -> Self {
let allocator = WrapAllocator::new();
let guard = unsafe { allocator.guard() };
let mut vector = Vec::new();
vector.push(String::from("We are"));
vector.push(String::from("So Back"));
TestParser {
some_reference: reference,
vector,
_allocator: allocator,
_guard: guard,
}
}
fn add_item(&mut self, item: String) {
self.vector.push(item);
}
}
#[test]
fn test_allocator_with_different_lifetimes() {
{
let text = String::from("test string");
{
let mut parser = TestParser::new(&text);
parser.add_item(String::from("Additional item"));
}
}
}
Rust playground with complete code: Rust Playground
How do I solve this use-after-free error? Can someone please help me?