From 11457a4ad942ec35952682f474556f6eae2d4db3 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 30 Jun 2019 10:59:42 +0200 Subject: [PATCH] fix comparing function pointers with intptrcast --- src/intptrcast.rs | 39 +++++++++++++------------ src/machine.rs | 2 -- tests/run-pass/intptrcast_format.rs | 6 ++++ tests/run-pass/intptrcast_format.stdout | 2 ++ 4 files changed, 29 insertions(+), 20 deletions(-) create mode 100644 tests/run-pass/intptrcast_format.rs create mode 100644 tests/run-pass/intptrcast_format.stdout diff --git a/src/intptrcast.rs b/src/intptrcast.rs index 7fd48defda1..f8102642bdb 100644 --- a/src/intptrcast.rs +++ b/src/intptrcast.rs @@ -1,25 +1,26 @@ -use std::cell::{Cell, RefCell}; +use std::cell::RefCell; +use std::collections::{HashMap, hash_map::Entry}; +use std::cmp::max; use rand::Rng; -use rustc::mir::interpret::{AllocId, Pointer, InterpResult}; -use rustc_mir::interpret::Memory; +use rustc_mir::interpret::{AllocId, Pointer, InterpResult, Memory, AllocCheck}; use rustc_target::abi::Size; use crate::{Evaluator, Tag, STACK_ADDR}; pub type MemoryExtra = RefCell; -#[derive(Clone, Debug, Default)] -pub struct AllocExtra { - base_addr: Cell> -} - #[derive(Clone, Debug)] pub struct GlobalState { /// This is used as a map between the address of each allocation and its `AllocId`. /// It is always sorted pub int_to_ptr_map: Vec<(u64, AllocId)>, + /// The base address for each allocation. We cannot put that into + /// `AllocExtra` because function pointers also have a base address, and + /// they do not have an `AllocExtra`. + /// This is the inverse of `int_to_ptr_map`. + pub base_addr: HashMap, /// This is used as a memory address when a new pointer is casted to an integer. It /// is always larger than any address that was previously made part of a block. pub next_base_addr: u64, @@ -29,6 +30,7 @@ impl Default for GlobalState { fn default() -> Self { GlobalState { int_to_ptr_map: Vec::default(), + base_addr: HashMap::default(), next_base_addr: STACK_ADDR, } } @@ -71,13 +73,13 @@ impl<'mir, 'tcx> GlobalState { memory: &Memory<'mir, 'tcx, Evaluator<'tcx>>, ) -> InterpResult<'tcx, u64> { let mut global_state = memory.extra.intptrcast.borrow_mut(); + let global_state = &mut *global_state; - let alloc = memory.get(ptr.alloc_id)?; - let align = alloc.align.bytes(); + let (size, align) = memory.get_size_and_align(ptr.alloc_id, AllocCheck::Live)?; - let base_addr = match alloc.extra.intptrcast.base_addr.get() { - Some(base_addr) => base_addr, - None => { + let base_addr = match global_state.base_addr.entry(ptr.alloc_id) { + Entry::Occupied(entry) => *entry.get(), + Entry::Vacant(entry) => { // This allocation does not have a base address yet, pick one. // Leave some space to the previous allocation, to give it some chance to be less aligned. let slack = { @@ -86,11 +88,12 @@ impl<'mir, 'tcx> GlobalState { rng.gen_range(0, 16) }; // 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)); + let base_addr = Self::align_addr(global_state.next_base_addr + slack, align.bytes()); + entry.insert(base_addr); - // Remember next base address. - global_state.next_base_addr = base_addr + alloc.bytes.len() as u64; + // Remember next base address. If this allocation is zero-sized, leave a gap + // of at least 1 to avoid two allocations having the same base address. + global_state.next_base_addr = base_addr + max(size.bytes(), 1); // 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)); @@ -99,7 +102,7 @@ impl<'mir, 'tcx> GlobalState { } }; - debug_assert_eq!(base_addr % align, 0); // sanity check + debug_assert_eq!(base_addr % align.bytes(), 0); // sanity check Ok(base_addr + ptr.offset.bytes()) } diff --git a/src/machine.rs b/src/machine.rs index 485286ea400..20fe2e055fb 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -42,7 +42,6 @@ impl Into> for MiriMemoryKind { #[derive(Debug, Clone)] pub struct AllocExtra { pub stacked_borrows: stacked_borrows::AllocExtra, - pub intptrcast: intptrcast::AllocExtra, } /// Extra global memory data @@ -277,7 +276,6 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> { mutability: alloc.mutability, extra: AllocExtra { stacked_borrows: stacks, - intptrcast: Default::default(), }, }; (Cow::Owned(alloc), base_tag) diff --git a/tests/run-pass/intptrcast_format.rs b/tests/run-pass/intptrcast_format.rs new file mode 100644 index 00000000000..c0d3e9398dc --- /dev/null +++ b/tests/run-pass/intptrcast_format.rs @@ -0,0 +1,6 @@ +// compile-flags: -Zmiri-seed= + +fn main() { + println!("Hello {}", 13); + println!("{:0