1
Fork 0

Rollup merge of #137802 - RalfJung:miri-native-call-exposed, r=oli-obk

miri native-call support: all previously exposed provenance is accessible to the callee

When Miri invokes a native C function, the memory C can access needs to be "prepared": to avoid false positives, we need to consider all that memory initialized, and we need to consider it to have arbitrary provenance. So far we did this for all pointers passed to C, but not for pointers that were exposed already before the native call. This PR adjusts the logic so that we now "prepare" all memory that has ever been exposed.

This fixes cases such as:
- cast a pointer to integer, send that integer to C, and access the memory there (`test_pass_ptr_as_int`)
- send a pointer to some memory to C, which stores it somewhere; then in Rust store another pointer in that memory, and access that via C (`test_pass_ptr_via_previously_shared_mem`)

r? `````@oli-obk`````
This commit is contained in:
Michael Goulet 2025-03-06 12:22:18 -05:00 committed by GitHub
commit b7b2179b5e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 125 additions and 64 deletions

View file

@ -955,18 +955,13 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
/// Handle the effect an FFI call might have on the state of allocations.
/// This overapproximates the modifications which external code might make to memory:
/// We set all reachable allocations as initialized, mark all provenances as exposed
/// We set all reachable allocations as initialized, mark all reachable provenances as exposed
/// and overwrite them with `Provenance::WILDCARD`.
pub fn prepare_for_native_call(
&mut self,
id: AllocId,
initial_prov: M::Provenance,
) -> InterpResult<'tcx> {
// Expose provenance of the root allocation.
M::expose_provenance(self, initial_prov)?;
///
/// The allocations in `ids` are assumed to be already exposed.
pub fn prepare_for_native_call(&mut self, ids: Vec<AllocId>) -> InterpResult<'tcx> {
let mut done = FxHashSet::default();
let mut todo = vec![id];
let mut todo = ids;
while let Some(id) = todo.pop() {
if !done.insert(id) {
// We already saw this allocation before, don't process it again.