Advertisement
NLinker

UB with incorrect unsafe usage

May 16th, 2019
492
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 1.25 KB | None | 0 0
  1. use std::cell::UnsafeCell;
  2.  
  3. pub struct OnceCell<T> {
  4.     inner: UnsafeCell<Option<T>>,
  5. }
  6.  
  7. impl<T> OnceCell<T> {
  8.     pub fn new() -> OnceCell<T> { OnceCell { inner: UnsafeCell::new(None) } }
  9.     pub fn get(&self) -> Option<&T> {
  10.         unsafe { &*self.inner.get() }.as_ref()
  11.     }
  12.     pub fn set(&self, value: T) -> Result<(), T> {
  13.         let slot = unsafe { &mut *self.inner.get() };
  14.         if slot.is_some() {
  15.             return Err(value);
  16.         }
  17.         *slot = Some(value);
  18.         Ok(())
  19.     }
  20.  
  21.     // UB!!!
  22.     pub fn get_or_init(&self, f: impl FnOnce() -> T) -> &T {
  23.         let slot = unsafe { &mut *self.inner.get() };
  24.         match slot {
  25.             None => {
  26.                 *slot = Some(f());
  27.                 slot.as_ref().unwrap()
  28.             }
  29.             Some(val) => val,
  30.         }
  31.     }
  32. }
  33.  
  34. pub fn main() {
  35.     let cell: OnceCell<Box<i32>> = OnceCell::new();
  36.     let mut r1: Option<&i32> = None;
  37.     let r2: &i32 = cell.get_or_init(|| {
  38.         r1 = Some(cell.get_or_init(|| Box::new(1)));
  39. //        r1 = Some(&*cell.get_or_init(|| Box::new(1)));
  40.         Box::new(2)
  41.     });
  42.     let r1: &i32 = r1.unwrap();
  43.     println!("{} {}", r1, r2);
  44. }
  45. /*
  46.   result is like
  47. ~/rust ❯❯❯ ./once_cell
  48. -1317687192 2
  49. */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement