commit
aefaa5b6f0
@ -1 +1 @@
|
||||
8aab472d52ba7314dc193c73abcd384e2586123c
|
||||
7f08d04d60d03e1a52dae61ce6aa50996898702b
|
||||
|
@ -76,27 +76,17 @@ fn alloc_id_from_addr(ecx: &MiriEvalContext<'mir, 'tcx>, addr: u64) -> Option<Al
|
||||
// This never overflows because `addr >= glb`
|
||||
let offset = addr - glb;
|
||||
// If the offset exceeds the size of the allocation, don't use this `alloc_id`.
|
||||
|
||||
if offset
|
||||
<= ecx
|
||||
.get_alloc_size_and_align(alloc_id, AllocCheck::MaybeDead)
|
||||
.unwrap()
|
||||
.0
|
||||
.bytes()
|
||||
{
|
||||
Some(alloc_id)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
let size = ecx.get_alloc_info(alloc_id).0;
|
||||
if offset <= size.bytes() { Some(alloc_id) } else { None }
|
||||
}
|
||||
}?;
|
||||
|
||||
// We only use this provenance if it has been exposed, *and* is still live.
|
||||
if global_state.exposed.contains(&alloc_id) {
|
||||
// FIXME: this catches `InterpError`, which we should not usually do.
|
||||
// We might need a proper fallible API from `memory.rs` to avoid this though.
|
||||
if ecx.get_alloc_size_and_align(alloc_id, AllocCheck::Live).is_ok() {
|
||||
return Some(alloc_id);
|
||||
let (_size, _align, kind) = ecx.get_alloc_info(alloc_id);
|
||||
match kind {
|
||||
AllocKind::LiveData | AllocKind::Function => return Some(alloc_id),
|
||||
AllocKind::Dead => {}
|
||||
}
|
||||
}
|
||||
|
||||
@ -174,9 +164,8 @@ fn alloc_base_addr(ecx: &MiriEvalContext<'mir, 'tcx>, alloc_id: AllocId) -> u64
|
||||
Entry::Occupied(entry) => *entry.get(),
|
||||
Entry::Vacant(entry) => {
|
||||
// There is nothing wrong with a raw pointer being cast to an integer only after
|
||||
// it became dangling. Hence `MaybeDead`.
|
||||
let (size, align) =
|
||||
ecx.get_alloc_size_and_align(alloc_id, AllocCheck::MaybeDead).unwrap();
|
||||
// it became dangling. Hence we allow dead allocations.
|
||||
let (size, align, _kind) = ecx.get_alloc_info(alloc_id);
|
||||
|
||||
// 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.
|
||||
|
@ -87,7 +87,7 @@ fn align_offset(
|
||||
let ptr = this.read_pointer(ptr_op)?;
|
||||
if let Ok((alloc_id, _offset, _)) = this.ptr_try_get_alloc_id(ptr) {
|
||||
// Only do anything if we can identify the allocation this goes to.
|
||||
let (_, cur_align) = this.get_alloc_size_and_align(alloc_id, AllocCheck::MaybeDead)?;
|
||||
let (_size, cur_align, _kind) = this.get_alloc_info(alloc_id);
|
||||
if cur_align.bytes() >= req_align {
|
||||
// If the allocation alignment is at least the required alignment we use the
|
||||
// real implementation.
|
||||
|
@ -849,8 +849,7 @@ fn reborrow(
|
||||
log_creation(this, current_span, alloc_id, base_offset, orig_tag)?;
|
||||
|
||||
// Ensure we bail out if the pointer goes out-of-bounds (see miri#1050).
|
||||
let (alloc_size, _) =
|
||||
this.get_alloc_size_and_align(alloc_id, AllocCheck::Dereferenceable)?;
|
||||
let (alloc_size, _) = this.get_live_alloc_size_and_align(alloc_id)?;
|
||||
if base_offset + size > alloc_size {
|
||||
throw_ub!(PointerOutOfBounds {
|
||||
alloc_id,
|
||||
@ -1088,18 +1087,16 @@ fn expose_tag(&mut self, alloc_id: AllocId, tag: SbTag) {
|
||||
// Function pointers and dead objects don't have an alloc_extra so we ignore them.
|
||||
// This is okay because accessing them is UB anyway, no need for any Stacked Borrows checks.
|
||||
// NOT using `get_alloc_extra_mut` since this might be a read-only allocation!
|
||||
// FIXME: this catches `InterpError`, which we should not usually do.
|
||||
// We might need a proper fallible API from `memory.rs` to avoid this though.
|
||||
match this.get_alloc_extra(alloc_id) {
|
||||
Ok(alloc_extra) => {
|
||||
let (_size, _align, kind) = this.get_alloc_info(alloc_id);
|
||||
match kind {
|
||||
AllocKind::LiveData => {
|
||||
// This should have alloc_extra data.
|
||||
let alloc_extra = this.get_alloc_extra(alloc_id).unwrap();
|
||||
trace!("Stacked Borrows tag {tag:?} exposed in {alloc_id}");
|
||||
alloc_extra.stacked_borrows.as_ref().unwrap().borrow_mut().exposed_tags.insert(tag);
|
||||
}
|
||||
Err(err) => {
|
||||
trace!(
|
||||
"Not exposing Stacked Borrows tag {tag:?} due to error \
|
||||
when accessing {alloc_id}: {err}"
|
||||
);
|
||||
AllocKind::Function | AllocKind::Dead => {
|
||||
// No stacked borrows on these allocations.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ fn f() {}
|
||||
|
||||
fn main() {
|
||||
let x: u8 = unsafe {
|
||||
*std::mem::transmute::<fn(), *const u8>(f) //~ ERROR contains a function
|
||||
*std::mem::transmute::<fn(), *const u8>(f) //~ ERROR out-of-bounds
|
||||
};
|
||||
panic!("this should never print: {}", x);
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: Undefined Behavior: accessing ALLOC which contains a function
|
||||
error: Undefined Behavior: dereferencing pointer failed: ALLOC has size 0, so pointer to 1 byte starting at offset 0 is out-of-bounds
|
||||
--> $DIR/deref_fn_ptr.rs:LL:CC
|
||||
|
|
||||
LL | *std::mem::transmute::<fn(), *const u8>(f)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ accessing ALLOC which contains a function
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: ALLOC has size 0, so pointer to 1 byte starting at offset 0 is out-of-bounds
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
Loading…
Reference in New Issue
Block a user