1
Fork 0

miri native_calls: ensure we actually expose *mutable* provenance to the memory FFI can access

This commit is contained in:
Ralf Jung 2025-03-11 14:32:03 +01:00
parent 705421b522
commit 3846f94230
4 changed files with 12 additions and 3 deletions

View file

@ -982,6 +982,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
todo.push(id); todo.push(id);
} }
} }
// Also expose the provenance of the interpreter-level allocation, so it can
// be read by FFI. The `black_box` is defensive programming as LLVM likes
// to (incorrectly) optimize away ptr2int casts whose result is unused.
std::hint::black_box(alloc.get_bytes_unchecked_raw().expose_provenance());
// Prepare for possible write from native code if mutable. // Prepare for possible write from native code if mutable.
if info.mutbl.is_mut() { if info.mutbl.is_mut() {

View file

@ -679,6 +679,11 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
// Set provenance of all bytes to wildcard. // Set provenance of all bytes to wildcard.
self.provenance.write_wildcards(self.len()); self.provenance.write_wildcards(self.len());
// Also expose the provenance of the interpreter-level allocation, so it can
// be written by FFI. The `black_box` is defensive programming as LLVM likes
// to (incorrectly) optimize away ptr2int casts whose result is unused.
std::hint::black_box(self.get_bytes_unchecked_raw_mut().expose_provenance());
Ok(()) Ok(())
} }

View file

@ -198,8 +198,8 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
} }
AllocKind::Dead => unreachable!(), AllocKind::Dead => unreachable!(),
}; };
// Ensure this pointer's provenance is exposed, so that it can be used by FFI code. // We don't have to expose this pointer yet, we do that in `prepare_for_native_call`.
return interp_ok(base_ptr.expose_provenance().try_into().unwrap()); return interp_ok(base_ptr.addr().try_into().unwrap());
} }
// We are not in native lib mode, so we control the addresses ourselves. // We are not in native lib mode, so we control the addresses ourselves.
if let Some((reuse_addr, clock)) = global_state.reuse.take_addr( if let Some((reuse_addr, clock)) = global_state.reuse.take_addr(

View file

@ -266,7 +266,7 @@ fn imm_to_carg<'tcx>(v: &ImmTy<'tcx>, cx: &impl HasDataLayout) -> InterpResult<'
CArg::USize(v.to_scalar().to_target_usize(cx)?.try_into().unwrap()), CArg::USize(v.to_scalar().to_target_usize(cx)?.try_into().unwrap()),
ty::RawPtr(..) => { ty::RawPtr(..) => {
let s = v.to_scalar().to_pointer(cx)?.addr(); let s = v.to_scalar().to_pointer(cx)?.addr();
// This relies on the `expose_provenance` in `addr_from_alloc_id`. // This relies on the `expose_provenance` in `prepare_for_native_call`.
CArg::RawPtr(std::ptr::with_exposed_provenance_mut(s.bytes_usize())) CArg::RawPtr(std::ptr::with_exposed_provenance_mut(s.bytes_usize()))
} }
_ => throw_unsup_format!("unsupported argument type for native call: {}", v.layout.ty), _ => throw_unsup_format!("unsupported argument type for native call: {}", v.layout.ty),