Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

intptrcast: Never allocate two objects directly adjecent #1930

Merged
merged 2 commits into from
Dec 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions src/intptrcast.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use std::cell::RefCell;
use std::cmp::max;
use std::collections::hash_map::Entry;

use log::trace;
Expand Down Expand Up @@ -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 (also see https://github.com/rust-lang/unsafe-code-guidelines/issues/313).
let size_plus_1 = size.bytes().checked_add(1).unwrap();
global_state.next_base_addr = base_addr.checked_add(size_plus_1).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));
Expand Down
22 changes: 22 additions & 0 deletions tests/run-pass/adjacent-allocs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
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 ();
// This is a ZST ptr just at the end of `n`, so it should be valid to deref.
unsafe { *zst }
RalfJung marked this conversation as resolved.
Show resolved Hide resolved
}
}