]> git.lizzy.rs Git - rust.git/commitdiff
tweak inttoptr allocation behavior
authorRalf Jung <post@ralfj.de>
Fri, 28 Jun 2019 08:16:10 +0000 (10:16 +0200)
committerRalf Jung <post@ralfj.de>
Sat, 29 Jun 2019 12:31:54 +0000 (14:31 +0200)
- Make `align_addr` not offset by `align` for no reason.
- Add some random slack between allocations to give them the chance to not be aligned.

src/eval.rs
src/fn_call.rs
src/intptrcast.rs
src/machine.rs

index 5f7d85b7445f7eaa25f234de97248f8ba8fe1702..ec97a77357cf8c12297a9d04fb2e13b994758df9 100644 (file)
@@ -10,7 +10,7 @@
 use crate::{
     InterpResult, InterpError, InterpretCx, StackPopCleanup, struct_error,
     Scalar, Tag, Pointer,
-    MiriMemoryKind, Evaluator, TlsEvalContextExt,
+    MemoryExtra, MiriMemoryKind, Evaluator, TlsEvalContextExt,
 };
 
 /// Configuration needed to spawn a Miri instance.
@@ -36,7 +36,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
     );
 
     // FIXME: InterpretCx::new should take an initial MemoryExtra
-    ecx.memory_mut().extra.rng = config.seed.map(StdRng::seed_from_u64);
+    ecx.memory_mut().extra = MemoryExtra::with_rng(config.seed.map(StdRng::seed_from_u64));
     
     let main_instance = ty::Instance::mono(ecx.tcx.tcx, main_id);
     let main_mir = ecx.load_mir(main_instance.def)?;
index e2a4daa6f385353757dbcfa7b5838d03fb4d0c32..66783f3200e0d9e6d76bc832e20f0d0c6ae22a07 100644 (file)
@@ -982,6 +982,7 @@ fn gen_random<'mir, 'tcx>(
 
     let data = match &mut this.memory_mut().extra.rng {
         Some(rng) => {
+            let mut rng = rng.borrow_mut();
             let mut data = vec![0; len];
             rng.fill_bytes(&mut data);
             data
index 176e1bc591c2e6b3259853818c1ec881f38ccdd9..aa2e11ac68dbe8e3b85267d786eb63c8f6dfca9a 100644 (file)
@@ -1,5 +1,7 @@
 use std::cell::{Cell, RefCell};
 
+use rand::Rng;
+
 use rustc::mir::interpret::{AllocId, Pointer, InterpResult};
 use rustc_mir::interpret::Memory;
 use rustc_target::abi::Size;
@@ -73,14 +75,23 @@ pub fn ptr_to_int(
         let mut global_state = memory.extra.intptrcast.borrow_mut();
 
         let alloc = memory.get(ptr.alloc_id)?;
+        let align = alloc.align.bytes();
 
         let base_addr = match alloc.extra.intptrcast.base_addr.get() { 
             Some(base_addr) => base_addr,
             None => {
                 // 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;
+                // Leave some space to the previous allocation, to give it some chance to be less aligned.
+                let slack = {
+                    let mut rng = memory.extra.rng.as_ref().unwrap().borrow_mut();
+                    rng.gen_range(0, align)
+                };
+                // From next_base_addr + slack, round up to adjust for alignment.
+                let base_addr = Self::align_addr(global_state.next_base_addr + slack, align);
                 alloc.extra.intptrcast.base_addr.set(Some(base_addr));
+
+                // Remember next base address.
+                global_state.next_base_addr = base_addr + alloc.bytes.len() as u64;
                 // 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((base_addr, ptr.alloc_id)); 
@@ -89,13 +100,28 @@ pub fn ptr_to_int(
             }
         };
 
-        debug_assert_eq!(base_addr % alloc.align.bytes(), 0); // sanity check
+        debug_assert_eq!(base_addr % align, 0); // sanity check
         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`
+    /// of `align` that is larger or equal to `addr`
     fn align_addr(addr: u64, align: u64) -> u64 {
-        addr + align - addr % align
+        if addr % align == 0 {
+            addr
+        } else {
+            addr + align - addr % align
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn test_align_addr() {
+        assert_eq!(GlobalState::align_addr(37, 4), 40);
+        assert_eq!(GlobalState::align_addr(44, 4), 44);
     }
 }
index eb177fa2a1859f770176da6570fd0c5e7143260e..c956fd0f33a980ffef0ed483fa6a941f49016992 100644 (file)
@@ -1,6 +1,7 @@
 use std::rc::Rc;
 use std::borrow::Cow;
 use std::collections::HashMap;
+use std::cell::RefCell;
 
 use rand::rngs::StdRng;
 
@@ -46,7 +47,7 @@ pub struct MemoryExtra {
     pub intptrcast: intptrcast::MemoryExtra,
     /// The random number generator to use if Miri is running in non-deterministic mode and to
     /// enable intptrcast
-    pub(crate) rng: Option<StdRng>
+    pub(crate) rng: Option<RefCell<StdRng>>
 }
 
 impl MemoryExtra {
@@ -54,7 +55,7 @@ pub fn with_rng(rng: Option<StdRng>) -> Self {
         MemoryExtra {
             stacked_borrows: Default::default(),
             intptrcast: Default::default(),
-            rng,
+            rng: rng.map(RefCell::new),
         }
     }
 }