fix comparing function pointers with intptrcast
This commit is contained in:
parent
1ec279f290
commit
11457a4ad9
@ -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())
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
6
tests/run-pass/intptrcast_format.rs
Normal file
6
tests/run-pass/intptrcast_format.rs
Normal file
@ -0,0 +1,6 @@
|
||||
// compile-flags: -Zmiri-seed=
|
||||
|
||||
fn main() {
|
||||
println!("Hello {}", 13);
|
||||
println!("{:0<width$}", "hello", width = 10);
|
||||
}
|
2
tests/run-pass/intptrcast_format.stdout
Normal file
2
tests/run-pass/intptrcast_format.stdout
Normal file
@ -0,0 +1,2 @@
|
||||
Hello 13
|
||||
hello00000
|
Loading…
x
Reference in New Issue
Block a user