]> git.lizzy.rs Git - rust.git/commitdiff
Implement intptrcast methods
authorChristian Poveda <cpovedar@fnal.gov>
Thu, 20 Jun 2019 19:21:47 +0000 (14:21 -0500)
committerChristian Poveda <cpovedar@fnal.gov>
Fri, 21 Jun 2019 19:55:37 +0000 (14:55 -0500)
src/intptrcast.rs [new file with mode: 0644]
src/lib.rs
src/memory.rs [new file with mode: 0644]
src/stacked_borrows.rs

diff --git a/src/intptrcast.rs b/src/intptrcast.rs
new file mode 100644 (file)
index 0000000..3e07f54
--- /dev/null
@@ -0,0 +1,20 @@
+use std::cell::RefCell;
+
+use rustc::mir::interpret::AllocId;
+
+pub type MemoryState = RefCell<GlobalState>;
+
+#[derive(Clone, Debug)]
+pub struct GlobalState {
+    pub vec: Vec<(u64, AllocId)>,
+    pub addr: u64,
+}
+
+impl Default for GlobalState {
+    fn default() -> Self {
+        GlobalState {
+            vec: Vec::default(),
+            addr: 2u64.pow(16)
+        }
+    }
+}
index 9072f141f89d9d3759873c71791352741b03f83f..f61abea62e0b6344704e2cb889bcecc985bbe5bf 100644 (file)
 mod range_map;
 mod mono_hash_map;
 mod stacked_borrows;
+mod intptrcast;
+mod memory;
 
 use std::collections::HashMap;
 use std::borrow::Cow;
+use std::cell::RefCell;
 use std::rc::Rc;
 
 use rand::rngs::StdRng;
@@ -48,6 +51,7 @@
 pub use crate::helpers::{EvalContextExt as HelpersEvalContextExt};
 use crate::mono_hash_map::MonoHashMap;
 pub use crate::stacked_borrows::{EvalContextExt as StackedBorEvalContextExt};
+use crate::memory::AllocExtra;
 
 // Used by priroda.
 pub use crate::stacked_borrows::{Tag, Permission, Stack, Stacks, Item};
@@ -206,6 +210,8 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
         }
     }
 
+    ecx.memory_mut().extra.seed = config.seed.clone();
+    
     assert!(args.next().is_none(), "start lang item has more arguments than expected");
 
     Ok(ecx)
@@ -386,8 +392,8 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
     type MemoryKinds = MiriMemoryKind;
 
     type FrameExtra = stacked_borrows::CallId;
-    type MemoryExtra = stacked_borrows::MemoryState;
-    type AllocExtra = stacked_borrows::Stacks;
+    type MemoryExtra = memory::MemoryState;
+    type AllocExtra = memory::AllocExtra;
     type PointerTag = Tag;
 
     type MemoryMap = MonoHashMap<AllocId, (MemoryKind<MiriMemoryKind>, Allocation<Tag, Self::AllocExtra>)>;
@@ -515,14 +521,14 @@ fn tag_allocation<'b>(
         let (extra, base_tag) = Stacks::new_allocation(
             id,
             Size::from_bytes(alloc.bytes.len() as u64),
-            Rc::clone(&memory.extra),
+            Rc::clone(&memory.extra.stacked),
             kind,
         );
         if kind != MiriMemoryKind::Static.into() {
             assert!(alloc.relocations.is_empty(), "Only statics can come initialized with inner pointers");
             // Now we can rely on the inner pointers being static, too.
         }
-        let mut memory_extra = memory.extra.borrow_mut();
+        let mut memory_extra = memory.extra.stacked.borrow_mut();
         let alloc: Allocation<Tag, Self::AllocExtra> = Allocation {
             bytes: alloc.bytes,
             relocations: Relocations::from_presorted(
@@ -535,7 +541,10 @@ fn tag_allocation<'b>(
             undef_mask: alloc.undef_mask,
             align: alloc.align,
             mutability: alloc.mutability,
-            extra,
+            extra: AllocExtra {
+                stacks: extra,
+                base_addr: RefCell::new(None),
+            },
         };
         (Cow::Owned(alloc), base_tag)
     }
@@ -545,7 +554,7 @@ fn tag_static_base_pointer(
         id: AllocId,
         memory: &Memory<'mir, 'tcx, Self>,
     ) -> Self::PointerTag {
-        memory.extra.borrow_mut().static_base_ptr(id)
+        memory.extra.stacked.borrow_mut().static_base_ptr(id)
     }
 
     #[inline(always)]
@@ -570,7 +579,7 @@ fn retag(
     fn stack_push(
         ecx: &mut InterpretCx<'mir, 'tcx, Self>,
     ) -> InterpResult<'tcx, stacked_borrows::CallId> {
-        Ok(ecx.memory().extra.borrow_mut().new_call())
+        Ok(ecx.memory().extra.stacked.borrow_mut().new_call())
     }
 
     #[inline(always)]
@@ -578,6 +587,76 @@ fn stack_pop(
         ecx: &mut InterpretCx<'mir, 'tcx, Self>,
         extra: stacked_borrows::CallId,
     ) -> InterpResult<'tcx> {
-        Ok(ecx.memory().extra.borrow_mut().end_call(extra))
+        Ok(ecx.memory().extra.stacked.borrow_mut().end_call(extra))
+    }
+
+    fn int_to_ptr(
+        int: u64,
+        memory: &Memory<'mir, 'tcx, Self>,
+    ) -> InterpResult<'tcx, Pointer<Self::PointerTag>> {
+        if int == 0 {
+            return err!(InvalidNullPointerUsage);
+        }
+        
+        if memory.extra.seed.is_none() {
+            return err!(ReadBytesAsPointer);
+        }
+
+        let extra = memory.extra.intptrcast.borrow();
+        
+        match extra.vec.binary_search_by_key(&int, |(int, _)| *int) {
+            Ok(pos) => {
+                let (_, alloc_id) = extra.vec[pos];
+                Ok(Pointer::new_with_tag(alloc_id, Size::from_bytes(0), Tag::Untagged))
+            }
+            Err(pos) => {
+                if pos > 0 {
+                    let (glb, alloc_id) = extra.vec[pos - 1];
+                    let offset = int - glb;
+                    if offset <= memory.get(alloc_id)?.bytes.len() as u64 {
+                        Ok(Pointer::new_with_tag(alloc_id, Size::from_bytes(offset), Tag::Untagged))
+                    } else {
+                        return err!(DanglingPointerDeref);
+                    }
+                } else {
+                    return err!(DanglingPointerDeref);
+                }
+            }
+        }
+    }
+    fn ptr_to_int(
+        ptr: Pointer<Self::PointerTag>,
+        memory: &Memory<'mir, 'tcx, Self>,
+    ) -> InterpResult<'tcx, u64> {
+        if memory.extra.seed.is_none() {
+            return err!(ReadPointerAsBytes);
+        }
+
+        let mut extra = memory.extra.intptrcast.borrow_mut();
+
+        let alloc = memory.get(ptr.alloc_id)?;
+
+        let base_addr = match alloc.extra.base_addr.borrow().clone() { 
+            Some(base_addr) => base_addr,
+            None => {
+                let base_addr = extra.addr;
+                extra.addr += alloc.bytes.len() as u64;
+
+                *alloc.extra.base_addr.borrow_mut() = Some(base_addr);
+
+                let elem = (base_addr, ptr.alloc_id);
+
+                if let Err(pos) = extra.vec.binary_search(&elem) {
+                    extra.vec.insert(pos, elem);
+                } else {
+                    return err!(Unreachable);
+                }
+
+                base_addr
+            }
+        };
+
+        Ok(base_addr + ptr.offset.bytes())
     }
 }
diff --git a/src/memory.rs b/src/memory.rs
new file mode 100644 (file)
index 0000000..13ffd85
--- /dev/null
@@ -0,0 +1,60 @@
+use std::cell::RefCell;
+
+use rustc_mir::interpret::{Pointer, Allocation, AllocationExtra, InterpResult};
+use rustc_target::abi::Size;
+
+use crate::{stacked_borrows, intptrcast};
+use crate::stacked_borrows::{Tag, AccessKind};
+
+#[derive(Default, Clone, Debug)]
+pub struct MemoryState {
+    pub stacked: stacked_borrows::MemoryState,
+    pub intptrcast: intptrcast::MemoryState,
+    pub seed: Option<u64>,
+}
+
+#[derive(Debug, Clone,)]
+pub struct AllocExtra {
+    pub stacks: stacked_borrows::Stacks,
+    pub base_addr: RefCell<Option<u64>>,
+}
+
+impl AllocationExtra<Tag> for AllocExtra {
+    #[inline(always)]
+    fn memory_read<'tcx>(
+        alloc: &Allocation<Tag, AllocExtra>,
+        ptr: Pointer<Tag>,
+        size: Size,
+    ) -> InterpResult<'tcx> {
+        trace!("read access with tag {:?}: {:?}, size {}", ptr.tag, ptr.erase_tag(), size.bytes());
+        alloc.extra.stacks.for_each(ptr, size, |stack, global| {
+            stack.access(AccessKind::Read, ptr.tag, global)?;
+            Ok(())
+        })
+    }
+
+    #[inline(always)]
+    fn memory_written<'tcx>(
+        alloc: &mut Allocation<Tag, AllocExtra>,
+        ptr: Pointer<Tag>,
+        size: Size,
+    ) -> InterpResult<'tcx> {
+        trace!("write access with tag {:?}: {:?}, size {}", ptr.tag, ptr.erase_tag(), size.bytes());
+        alloc.extra.stacks.for_each(ptr, size, |stack, global| {
+            stack.access(AccessKind::Write, ptr.tag, global)?;
+            Ok(())
+        })
+    }
+
+    #[inline(always)]
+    fn memory_deallocated<'tcx>(
+        alloc: &mut Allocation<Tag, AllocExtra>,
+        ptr: Pointer<Tag>,
+        size: Size,
+    ) -> InterpResult<'tcx> {
+        trace!("deallocation with tag {:?}: {:?}, size {}", ptr.tag, ptr.erase_tag(), size.bytes());
+        alloc.extra.stacks.for_each(ptr, size, |stack, global| {
+            stack.dealloc(ptr.tag, global)
+        })
+    }
+}
index f7617676701c5a226622d57d21c09c56121c9f1b..ea70c28709cee0677c0cca270120b09d9cc9354f 100644 (file)
@@ -10,8 +10,8 @@
 
 use crate::{
     InterpResult, InterpError, MiriEvalContext, HelpersEvalContextExt, Evaluator, MutValueVisitor,
-    MemoryKind, MiriMemoryKind, RangeMap, Allocation, AllocationExtra, AllocId, CheckInAllocMsg,
-    Pointer, Immediate, ImmTy, PlaceTy, MPlaceTy,
+    MemoryKind, MiriMemoryKind, RangeMap, AllocId, CheckInAllocMsg, Pointer, Immediate, ImmTy, 
+    PlaceTy, MPlaceTy,
 };
 
 pub type PtrId = NonZeroU64;
@@ -286,7 +286,7 @@ fn check_protector(item: &Item, tag: Option<Tag>, global: &GlobalState) -> Inter
 
     /// Test if a memory `access` using pointer tagged `tag` is granted.
     /// If yes, return the index of the item that granted it.
-    fn access(
+    pub(crate) fn access(
         &mut self,
         access: AccessKind,
         tag: Tag,
@@ -336,7 +336,7 @@ fn access(
 
     /// Deallocate a location: Like a write access, but also there must be no
     /// active protectors at all because we will remove all items.
-    fn dealloc(
+    pub(crate) fn dealloc(
         &mut self,
         tag: Tag,
         global: &GlobalState,
@@ -429,14 +429,15 @@ fn new(
         let stack = Stack {
             borrows: vec![item],
         };
+
         Stacks {
             stacks: RefCell::new(RangeMap::new(size, stack)),
-            global: extra,
+            global: extra, 
         }
     }
 
     /// Call `f` on every stack in the range.
-    fn for_each(
+    pub(crate) fn for_each(
         &self,
         ptr: Pointer<Tag>,
         size: Size,
@@ -456,7 +457,7 @@ impl Stacks {
     pub fn new_allocation(
         id: AllocId,
         size: Size,
-        extra: MemoryState,
+        extra: MemoryState, 
         kind: MemoryKind<MiriMemoryKind>,
     ) -> (Self, Tag) {
         let (tag, perm) = match kind {
@@ -477,46 +478,6 @@ pub fn new_allocation(
     }
 }
 
-impl AllocationExtra<Tag> for Stacks {
-    #[inline(always)]
-    fn memory_read<'tcx>(
-        alloc: &Allocation<Tag, Stacks>,
-        ptr: Pointer<Tag>,
-        size: Size,
-    ) -> InterpResult<'tcx> {
-        trace!("read access with tag {:?}: {:?}, size {}", ptr.tag, ptr.erase_tag(), size.bytes());
-        alloc.extra.for_each(ptr, size, |stack, global| {
-            stack.access(AccessKind::Read, ptr.tag, global)?;
-            Ok(())
-        })
-    }
-
-    #[inline(always)]
-    fn memory_written<'tcx>(
-        alloc: &mut Allocation<Tag, Stacks>,
-        ptr: Pointer<Tag>,
-        size: Size,
-    ) -> InterpResult<'tcx> {
-        trace!("write access with tag {:?}: {:?}, size {}", ptr.tag, ptr.erase_tag(), size.bytes());
-        alloc.extra.for_each(ptr, size, |stack, global| {
-            stack.access(AccessKind::Write, ptr.tag, global)?;
-            Ok(())
-        })
-    }
-
-    #[inline(always)]
-    fn memory_deallocated<'tcx>(
-        alloc: &mut Allocation<Tag, Stacks>,
-        ptr: Pointer<Tag>,
-        size: Size,
-    ) -> InterpResult<'tcx> {
-        trace!("deallocation with tag {:?}: {:?}, size {}", ptr.tag, ptr.erase_tag(), size.bytes());
-        alloc.extra.for_each(ptr, size, |stack, global| {
-            stack.dealloc(ptr.tag, global)
-        })
-    }
-}
-
 /// Retagging/reborrowing.  There is some policy in here, such as which permissions
 /// to grant for which references, and when to add protectors.
 impl<'mir, 'tcx> EvalContextPrivExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
@@ -553,14 +514,14 @@ fn reborrow(
                     // We are only ever `SharedReadOnly` inside the frozen bits.
                     let perm = if frozen { Permission::SharedReadOnly } else { Permission::SharedReadWrite };
                     let item = Item { perm, tag: new_tag, protector };
-                    alloc.extra.for_each(cur_ptr, size, |stack, global| {
+                    alloc.extra.stacks.for_each(cur_ptr, size, |stack, global| {
                         stack.grant(cur_ptr.tag, item, global)
                     })
                 });
             }
         };
         let item = Item { perm, tag: new_tag, protector };
-        alloc.extra.for_each(ptr, size, |stack, global| {
+        alloc.extra.stacks.for_each(ptr, size, |stack, global| {
             stack.grant(ptr.tag, item, global)
         })
     }
@@ -587,7 +548,7 @@ fn retag_reference(
         // Compute new borrow.
         let new_tag = match kind {
             RefKind::Raw { .. } => Tag::Untagged,
-            _ => Tag::Tagged(this.memory().extra.borrow_mut().new_ptr()),
+            _ => Tag::Tagged(this.memory().extra.stacked.borrow_mut().new_ptr()),
         };
 
         // Reborrow.
@@ -621,7 +582,7 @@ fn qualify(ty: ty::Ty<'_>, kind: RetagKind) -> Option<(RefKind, bool)> {
                 ty::RawPtr(tym) if kind == RetagKind::Raw =>
                     Some((RefKind::Raw { mutable: tym.mutbl == MutMutable }, false)),
                 // Boxes do not get a protector: protectors reflect that references outlive the call
-                // they were passed in to; that's just not the case for boxes.
+            // they were passed in to; that's just not the case for boxes.
                 ty::Adt(..) if ty.is_box() => Some((RefKind::Unique { two_phase: false }, false)),
                 _ => None,
             }