Skip to content

Instantly share code, notes, and snippets.

@VigneshChennai
Created November 2, 2020 04:13
Show Gist options
  • Save VigneshChennai/541b173f8c9402b4419b97321a7e42c9 to your computer and use it in GitHub Desktop.
Save VigneshChennai/541b173f8c9402b4419b97321a7e42c9 to your computer and use it in GitHub Desktop.
Rust: Example of how "not owning a generic T" can allow unsound usage
#![feature(dropck_eyepatch)]
use std::alloc::Layout;
use std::ops::{Deref, DerefMut};
// use std::marker::PhantomData;
struct InHeap<T: Sized> {
ptr: *const T,
//_m: PhantomData<T> // Using PhantomData will prevent "unsound usage"
}
impl<T> InHeap<T> {
fn new(v: T) -> Self {
let ptr = unsafe { std::alloc::alloc(Layout::new::<T>()) };
if ptr.is_null() {
// abort on out of memory error
std::alloc::handle_alloc_error(Layout::new::<T>());
} else {
unsafe { std::ptr::write(ptr as *mut T, v); }
InHeap {
ptr: ptr as *const T,
//_m: PhantomData
}
}
}
}
impl<T> Deref for InHeap<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &*self.ptr }
}
}
impl<T> DerefMut for InHeap<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *(self.ptr as *mut T) }
}
}
unsafe impl<#[may_dangle] T> Drop for InHeap<T> {
fn drop(&mut self) {
unsafe {
std::ptr::drop_in_place(self.ptr as *mut T);
std::alloc::dealloc(self.ptr as *mut u8, Layout::new::<T>())
};
}
}
#[derive(Debug)]
struct MyString<'a>(&'a String);
impl<'a> Drop for MyString<'a> {
fn drop(&mut self) {
println!("Accessing '{}' in MyString's Drop", self.0)
}
}
fn main() {
let mut foo = InHeap::new(None);
let mut bar = String::from("Hello everyone!");
*foo = Some(MyString(&mut bar));
drop(bar);
println!("The variable bar='Hello everyone!' is drop. \
Any further access to the value is UB"
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment