This commit is contained in:
The Miri Cronjob Bot 2024-09-01 05:04:43 +00:00
parent a9477c7537
commit b71297f670
5 changed files with 37 additions and 21 deletions

View file

@ -185,8 +185,11 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
panic!("Miri ran out of memory: cannot create allocation of {size:?} bytes")
});
let ptr = prepared_bytes.as_ptr();
// Store prepared allocation space to be picked up for use later.
global_state.prepared_alloc_bytes.try_insert(alloc_id, prepared_bytes).unwrap();
// Store prepared allocation space to be picked up for use later.
global_state
.prepared_alloc_bytes
.try_insert(alloc_id, prepared_bytes)
.unwrap();
ptr
} else {
ecx.get_alloc_bytes_unchecked_raw(alloc_id)?
@ -196,16 +199,19 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
}
AllocKind::Function | AllocKind::VTable => {
// Allocate some dummy memory to get a unique address for this function/vtable.
let alloc_bytes = MiriAllocBytes::from_bytes(&[0u8; 1], Align::from_bytes(1).unwrap());
let alloc_bytes = MiriAllocBytes::from_bytes(
&[0u8; 1],
Align::from_bytes(1).unwrap(),
);
// We don't need to expose these bytes as nobody is allowed to access them.
let addr = alloc_bytes.as_ptr().addr().try_into().unwrap();
// Leak the underlying memory to ensure it remains unique.
std::mem::forget(alloc_bytes);
addr
}
AllocKind::Dead => unreachable!()
AllocKind::Dead => unreachable!(),
}
} else if let Some((reuse_addr, clock)) = global_state.reuse.take_addr(
} else if let Some((reuse_addr, clock)) = global_state.reuse.take_addr(
&mut *rng,
size,
align,
@ -359,7 +365,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// This returns some prepared `MiriAllocBytes`, either because `addr_from_alloc_id` reserved
// memory space in the past, or by doing the pre-allocation right upon being called.
fn get_global_alloc_bytes(&self, id: AllocId, kind: MemoryKind, bytes: &[u8], align: Align) -> InterpResult<'tcx, MiriAllocBytes> {
fn get_global_alloc_bytes(
&self,
id: AllocId,
kind: MemoryKind,
bytes: &[u8],
align: Align,
) -> InterpResult<'tcx, MiriAllocBytes> {
let ecx = self.eval_context_ref();
Ok(if ecx.machine.native_lib.is_some() {
// In native lib mode, MiriAllocBytes for global allocations are handled via `prepared_alloc_bytes`.

View file

@ -888,8 +888,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
}
let alloc = this.ctfe_query(|tcx| tcx.eval_static_initializer(def_id))?;
// We make a full copy of this allocation.
let mut alloc =
alloc.inner().adjust_from_tcx(&this.tcx, |bytes, align| Ok(MiriAllocBytes::from_bytes(std::borrow::Cow::Borrowed(bytes), align)), |ptr| this.global_root_pointer(ptr))?;
let mut alloc = alloc.inner().adjust_from_tcx(
&this.tcx,
|bytes, align| {
Ok(MiriAllocBytes::from_bytes(std::borrow::Cow::Borrowed(bytes), align))
},
|ptr| this.global_root_pointer(ptr),
)?;
// This allocation will be deallocated when the thread dies, so it is not in read-only memory.
alloc.mutability = Mutability::Mut;
// Create a fresh allocation with this content.

View file

@ -1277,12 +1277,12 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
) -> InterpResult<'tcx, Cow<'b, Allocation<Self::Provenance, Self::AllocExtra, Self::Bytes>>>
{
let kind = Self::GLOBAL_KIND.unwrap().into();
let alloc = alloc.adjust_from_tcx(&ecx.tcx,
let alloc = alloc.adjust_from_tcx(
&ecx.tcx,
|bytes, align| ecx.get_global_alloc_bytes(id, kind, bytes, align),
|ptr| ecx.global_root_pointer(ptr),
)?;
let extra =
Self::init_alloc_extra(ecx, id, kind, alloc.size(), alloc.align)?;
let extra = Self::init_alloc_extra(ecx, id, kind, alloc.size(), alloc.align)?;
Ok(Cow::Owned(alloc.with_extra(extra)))
}

View file

@ -240,13 +240,16 @@ fn imm_to_carg<'tcx>(v: ImmTy<'tcx>, cx: &impl HasDataLayout) -> InterpResult<'t
ty::RawPtr(_, mutability) => {
// Arbitrary mutable pointer accesses are not currently supported in Miri.
if mutability.is_mut() {
throw_unsup_format!("unsupported mutable pointer type for native call: {}", v.layout.ty);
throw_unsup_format!(
"unsupported mutable pointer type for native call: {}",
v.layout.ty
);
} else {
let s = v.to_scalar().to_pointer(cx)?.addr();
// This relies on the `expose_provenance` in `addr_from_alloc_id`.
CArg::RawPtr(std::ptr::with_exposed_provenance_mut(s.bytes_usize()))
}
},
}
_ => throw_unsup_format!("unsupported argument type for native call: {}", v.layout.ty),
})
}

View file

@ -26,7 +26,7 @@ fn test_pointer() {
fn test_simple() {
#[repr(C)]
struct Simple {
field: i32
field: i32,
}
extern "C" {
@ -41,7 +41,7 @@ fn test_simple() {
// Test function that dereferences nested struct pointers and accesses fields.
fn test_nested() {
use std::ptr::NonNull;
#[derive(Debug, PartialEq, Eq)]
#[repr(C)]
struct Nested {
@ -62,7 +62,6 @@ fn test_nested() {
// Test function that dereferences static struct pointers and accesses fields.
fn test_static() {
#[repr(C)]
struct Static {
value: i32,
@ -72,11 +71,8 @@ fn test_static() {
extern "C" {
fn access_static(n_ptr: *const Static) -> i32;
}
static STATIC: Static = Static {
value: 9001,
recurse: &STATIC,
};
static STATIC: Static = Static { value: 9001, recurse: &STATIC };
assert_eq!(unsafe { access_static(&STATIC) }, 9001);
}