intptrcast: Never allocate two objects directly adjecent
When two objects directly follow each other in memory, what is the provenance of an integer cast to a pointer that points directly between them? For a zero-size region, it could point into the end of the first object, or the start of the second. We can avoid answering this difficult question by simply never allocating two objects directly beside each other. This fixes some of the false positives from #1866.
This commit is contained in:
parent
5e9cf62b89
commit
b0a463334c
2 changed files with 26 additions and 4 deletions
|
|
@ -1,5 +1,4 @@
|
|||
use std::cell::RefCell;
|
||||
use std::cmp::max;
|
||||
use std::collections::hash_map::Entry;
|
||||
|
||||
use log::trace;
|
||||
|
|
@ -107,9 +106,11 @@ impl<'mir, 'tcx> GlobalState {
|
|||
slack,
|
||||
);
|
||||
|
||||
// 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.checked_add(max(size.bytes(), 1)).unwrap();
|
||||
// Remember next base address. Leave a gap of at least 1 to avoid two zero-sized allocations
|
||||
// having the same base address, and to avoid ambiguous provenance for the address between two
|
||||
// allocations.
|
||||
let bytes = size.bytes().checked_add(1).unwrap();
|
||||
global_state.next_base_addr = base_addr.checked_add(bytes).unwrap();
|
||||
// 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, alloc_id));
|
||||
|
|
|
|||
21
tests/run-pass/adjacent-allocs.rs
Normal file
21
tests/run-pass/adjacent-allocs.rs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
fn main() {
|
||||
// The slack between allocations is random.
|
||||
// Loop a few times to hit the zero-slack case.
|
||||
for _ in 0..1024 {
|
||||
let n = 0u64;
|
||||
let ptr: *const u64 = &n;
|
||||
|
||||
// Allocate a new stack variable whose lifetime quickly ends.
|
||||
// If there's a chance that &m == ptr.add(1), then an int-to-ptr cast of
|
||||
// that value will have ambiguous provenance between n and m.
|
||||
// See https://github.com/rust-lang/miri/issues/1866#issuecomment-985770125
|
||||
{
|
||||
let m = 0u64;
|
||||
let _ = &m as *const u64;
|
||||
}
|
||||
|
||||
let iptr = ptr as usize;
|
||||
let zst = (iptr + 8) as *const ();
|
||||
unsafe { *zst }
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue