diff --git a/src/intptrcast.rs b/src/intptrcast.rs index a95b20868d2..0ef5b08f9e4 100644 --- a/src/intptrcast.rs +++ b/src/intptrcast.rs @@ -76,27 +76,17 @@ impl<'mir, 'tcx> GlobalStateInner { // 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 @@ impl<'mir, 'tcx> GlobalStateInner { 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. diff --git a/src/shims/mod.rs b/src/shims/mod.rs index f2688bb08ca..2423ffaf5fe 100644 --- a/src/shims/mod.rs +++ b/src/shims/mod.rs @@ -87,7 +87,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx 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. diff --git a/src/stacked_borrows.rs b/src/stacked_borrows.rs index ea1132d3e12..66f756d7b08 100644 --- a/src/stacked_borrows.rs +++ b/src/stacked_borrows.rs @@ -849,8 +849,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx 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 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx // 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. } } } diff --git a/tests/fail/function_pointers/deref_fn_ptr.rs b/tests/fail/function_pointers/deref_fn_ptr.rs index e604f96ea16..f22f73487b4 100644 --- a/tests/fail/function_pointers/deref_fn_ptr.rs +++ b/tests/fail/function_pointers/deref_fn_ptr.rs @@ -2,7 +2,7 @@ fn f() {} fn main() { let x: u8 = unsafe { - *std::mem::transmute::(f) //~ ERROR contains a function + *std::mem::transmute::(f) //~ ERROR out-of-bounds }; panic!("this should never print: {}", x); } diff --git a/tests/fail/function_pointers/deref_fn_ptr.stderr b/tests/fail/function_pointers/deref_fn_ptr.stderr index 1e3da2726d4..619b58f699a 100644 --- a/tests/fail/function_pointers/deref_fn_ptr.stderr +++ b/tests/fail/function_pointers/deref_fn_ptr.stderr @@ -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::(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