]> git.lizzy.rs Git - rust.git/commitdiff
Fix alignment of base addresses
authorChristian Poveda <cpovedar@fnal.gov>
Tue, 25 Jun 2019 19:07:23 +0000 (14:07 -0500)
committerChristian Poveda <christianpoveda@protonmail.com>
Wed, 26 Jun 2019 14:08:28 +0000 (09:08 -0500)
src/intptrcast.rs
src/lib.rs
tests/run-pass/intptrcast-truncate.rs [deleted file]
tests/run-pass/intptrcast.rs [new file with mode: 0644]

index c48e7b7772b1de1bafeaa42f784864ce588f911f..ad0489fa7de860918635caba838441246e8368da 100644 (file)
@@ -36,25 +36,25 @@ fn default() -> Self {
 
 impl<'mir, 'tcx> GlobalState {
     pub fn int_to_ptr(
-        base_addr: u64,
+        int: u64,
         memory: &Memory<'mir, 'tcx, Evaluator<'tcx>>,
     ) -> InterpResult<'tcx, Pointer<Tag>> {
         let global_state = memory.extra.intptrcast.borrow();
         
-        match global_state.int_to_ptr_map.binary_search_by_key(&base_addr, |(addr, _)| *addr) {
+        match global_state.int_to_ptr_map.binary_search_by_key(&int, |(addr, _)| *addr) {
             Ok(pos) => {
                 let (_, alloc_id) = global_state.int_to_ptr_map[pos];
-                // `base_addr` is the starting address for an allocation, the offset should be
+                // `int` is equal to the starting address for an allocation, the offset should be
                 // zero. The pointer is untagged because it was created from a cast
                 Ok(Pointer::new_with_tag(alloc_id, Size::from_bytes(0), Tag::Untagged))
             },
             Err(0) => err!(DanglingPointerDeref), 
             Err(pos) => {
-                // This is the gargest of the adresses smaller than `base_addr`,
+                // This is the largest of the adresses smaller than `int`,
                 // i.e. the greatest lower bound (glb)
                 let (glb, alloc_id) = global_state.int_to_ptr_map[pos - 1];
-                // This never overflows because `base_addr >= glb`
-                let offset = base_addr - glb;
+                // This never overflows because `int >= glb`
+                let offset = int - glb;
                 // If the offset exceeds the size of the allocation, this access is illegal
                 if offset <= memory.get(alloc_id)?.bytes.len() as u64 {
                     // This pointer is untagged because it was created from a cast
@@ -77,16 +77,13 @@ pub fn ptr_to_int(
         let base_addr = match alloc.extra.intptrcast.base_addr.get() { 
             Some(base_addr) => base_addr,
             None => {
-                let base_addr = global_state.next_base_addr;
-                global_state.next_base_addr += alloc.bytes.len() as u64;
-
+                // This allocation does not have a base address yet, pick one.
+                let base_addr = Self::align_addr(global_state.next_base_addr, alloc.align.bytes());
+                global_state.next_base_addr = base_addr + alloc.bytes.len() as u64;
                 alloc.extra.intptrcast.base_addr.set(Some(base_addr));
-
-                let elem = (base_addr, ptr.alloc_id);
-
                 // Given that `next_base_addr` increases in each allocation, pushing the
                 // corresponding tuple keeps `int_to_ptr_map` sorted
-                global_state.int_to_ptr_map.push(elem); 
+                global_state.int_to_ptr_map.push((base_addr, ptr.alloc_id)); 
 
                 base_addr
             }
@@ -94,4 +91,10 @@ pub fn ptr_to_int(
 
         Ok(base_addr + ptr.offset.bytes())
     }
+
+    /// Shifts `addr` to make it aligned with `align` by rounding `addr` to the smallest multiple
+    /// of `align` that is strictly larger to `addr`
+    fn align_addr(addr: u64, align: u64) -> u64 {
+        addr + align - addr % align
+    }
 }
index 77acd3045da573c147d5601ee3c1f18932e6441d..6b1ada69d3975dfc38e9e8e8e6acd833a1699f55 100644 (file)
@@ -85,6 +85,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
         Evaluator::new(config.validate),
     );
 
+    // FIXME: InterpretCx::new should take an initial MemoryExtra
     ecx.memory_mut().extra.rng = config.seed.map(StdRng::seed_from_u64);
     
     let main_instance = ty::Instance::mono(ecx.tcx.tcx, main_id);
diff --git a/tests/run-pass/intptrcast-truncate.rs b/tests/run-pass/intptrcast-truncate.rs
deleted file mode 100644 (file)
index 4ff57ca..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-// compile-flags: -Zmiri-seed=0000000000000000
-
-fn main() {
-    let x = &42 as *const i32 as usize; 
-    let y = x * 2;
-    assert_eq!(y, x + x);
-    let z = y as u8 as usize;
-    assert_eq!(z, y % 256);
-}
diff --git a/tests/run-pass/intptrcast.rs b/tests/run-pass/intptrcast.rs
new file mode 100644 (file)
index 0000000..4ff57ca
--- /dev/null
@@ -0,0 +1,9 @@
+// compile-flags: -Zmiri-seed=0000000000000000
+
+fn main() {
+    let x = &42 as *const i32 as usize; 
+    let y = x * 2;
+    assert_eq!(y, x + x);
+    let z = y as u8 as usize;
+    assert_eq!(z, y % 256);
+}