fix comparing function pointers with intptrcast

This commit is contained in:
Ralf Jung 2019-06-30 10:59:42 +02:00
parent 1ec279f290
commit 11457a4ad9
4 changed files with 29 additions and 20 deletions

View File

@ -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<GlobalState>;
#[derive(Clone, Debug, Default)]
pub struct AllocExtra {
base_addr: Cell<Option<u64>>
}
#[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<AllocId, u64>,
/// 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())
}

View File

@ -42,7 +42,6 @@ impl Into<MemoryKind<MiriMemoryKind>> 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)

View File

@ -0,0 +1,6 @@
// compile-flags: -Zmiri-seed=
fn main() {
println!("Hello {}", 13);
println!("{:0<width$}", "hello", width = 10);
}

View File

@ -0,0 +1,2 @@
Hello 13
hello00000