Skip to content

Commit 6a7c730

Browse files
committed
start implementing alloc_mark_init_rec, write_zero_if_uninit, write ptr_write_access.rs tests (modifying, initializing memory, provenance)
1 parent 5926e82 commit 6a7c730

File tree

6 files changed

+142
-13
lines changed

6 files changed

+142
-13
lines changed

compiler/rustc_const_eval/src/interpret/memory.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -944,6 +944,26 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
944944
interp_ok(())
945945
}
946946

947+
pub fn alloc_mark_init_rec(&mut self, id: AllocId) -> InterpResult<'tcx> {
948+
let mut reachable = rustc_data_structures::fx::FxHashSet::default();
949+
let mut todo = vec![id];
950+
while let Some(id) = todo.pop() {
951+
if reachable.insert(id) {
952+
// This is a new allocation, add the allocation it points to `todo`.
953+
if let Ok((alloc, _)) = self.get_alloc_raw_mut(id) {
954+
let range = AllocRange { start: Size::ZERO, size: Size::from_bytes(alloc.len()) };
955+
alloc
956+
.write_zero_if_uninit(range)
957+
.map_err(|e| e.to_interp_error(id))?;
958+
todo.extend(
959+
alloc.provenance().provenances().filter_map(|prov| prov.get_alloc_id()),
960+
);
961+
}
962+
}
963+
}
964+
Ok(())
965+
}
966+
947967
/// Create a lazy debug printer that prints the given allocation and all allocations it points
948968
/// to, recursively.
949969
#[must_use]

compiler/rustc_middle/src/mir/interpret/allocation.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -643,6 +643,12 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
643643
Ok(())
644644
}
645645

646+
/// Write zeroes to the unitialized memory within the given memory range.
647+
pub fn write_zero_if_uninit(&mut self, range: AllocRange) -> AllocResult {
648+
self.mark_init(range, true); // TODO: Write zeroes?
649+
Ok(())
650+
}
651+
646652
/// Remove all provenance in the given memory range.
647653
pub fn clear_provenance(&mut self, cx: &impl HasDataLayout, range: AllocRange) -> AllocResult {
648654
self.provenance.clear(range, cx)?;

src/tools/miri/src/shims/native_lib.rs

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -152,9 +152,18 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
152152
if !matches!(arg.layout.backend_repr, BackendRepr::Scalar(_)) {
153153
throw_unsup_format!("only scalar argument types are support for native calls")
154154
}
155-
libffi_args.push(imm_to_carg(this.read_immediate(arg)?, this)?);
155+
let imm = this.read_immediate(arg)?;
156+
if matches!(arg.layout.ty.kind(), ty::RawPtr(_, rustc_ast::Mutability::Mut)) {
157+
let ptr = this.read_pointer(&imm)?;
158+
let Ok((alloc_id, _size, _prov_extra)) = this.ptr_try_get_alloc_id(ptr, 0) else {
159+
todo!(); // TODO: Handle absolute-address-returned case.
160+
};
161+
this.alloc_mark_init_rec(alloc_id)?;
162+
}
163+
libffi_args.push(imm_to_carg(imm, this)?);
156164
}
157165

166+
// TODO: Directly collect into correct Vec? -- lifetime issues.
158167
// Convert them to `libffi::high::Arg` type.
159168
let libffi_args = libffi_args
160169
.iter()
@@ -238,18 +247,10 @@ fn imm_to_carg<'tcx>(v: ImmTy<'tcx>, cx: &impl HasDataLayout) -> InterpResult<'t
238247
ty::Uint(UintTy::U64) => CArg::UInt64(v.to_scalar().to_u64()?),
239248
ty::Uint(UintTy::Usize) =>
240249
CArg::USize(v.to_scalar().to_target_usize(cx)?.try_into().unwrap()),
241-
ty::RawPtr(_, mutability) => {
242-
// Arbitrary mutable pointer accesses are not currently supported in Miri.
243-
if mutability.is_mut() {
244-
throw_unsup_format!(
245-
"unsupported mutable pointer type for native call: {}",
246-
v.layout.ty
247-
);
248-
} else {
249-
let s = v.to_scalar().to_pointer(cx)?.addr();
250-
// This relies on the `expose_provenance` in `addr_from_alloc_id`.
251-
CArg::RawPtr(std::ptr::with_exposed_provenance_mut(s.bytes_usize()))
252-
}
250+
ty::RawPtr(..) => {
251+
let s = v.to_scalar().to_pointer(cx)?.addr();
252+
// This relies on the `expose_provenance` in `addr_from_alloc_id`.
253+
CArg::RawPtr(std::ptr::with_exposed_provenance_mut(s.bytes_usize()))
253254
}
254255
_ => throw_unsup_format!("unsupported argument type for native call: {}", v.layout.ty),
255256
})
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// Only works on Unix targets
2+
//@ignore-target: windows wasm
3+
//@only-on-host
4+
5+
use std::mem::MaybeUninit;
6+
7+
fn main() {
8+
test_modify_int();
9+
10+
test_init_int();
11+
12+
test_init_array();
13+
14+
test_swap_ptr();
15+
}
16+
17+
fn test_modify_int() {
18+
extern "C" {
19+
fn modify_int(ptr: *mut i32);
20+
}
21+
22+
let mut x = 1;
23+
unsafe { modify_int(&mut x) };
24+
25+
assert_eq!(x, 3);
26+
}
27+
28+
fn test_init_int() {
29+
extern "C" {
30+
fn init_int(ptr: *mut i32);
31+
}
32+
33+
let mut x = MaybeUninit::<i32>::uninit();
34+
let x = unsafe {
35+
init_int(x.as_mut_ptr());
36+
x.assume_init()
37+
};
38+
39+
assert_eq!(x, 29);
40+
}
41+
42+
fn test_init_array() {
43+
extern "C" {
44+
fn init_array(ptr: *mut i32, len: usize, value: i32);
45+
}
46+
47+
const LEN: usize = 4;
48+
let init_value = 5;
49+
50+
let mut array = MaybeUninit::<[i32; LEN]>::uninit();
51+
let array = unsafe {
52+
init_array((*array.as_mut_ptr()).as_mut_ptr(), LEN, init_value);
53+
array.assume_init()
54+
};
55+
56+
assert_eq!(array, [init_value; LEN]);
57+
}
58+
59+
fn test_swap_ptr() {
60+
extern "C" {
61+
fn swap_ptr(x: *mut *const i32, y: *mut *const i32);
62+
}
63+
64+
let x = 6;
65+
let [mut ptr0, mut ptr1] = [&x, std::ptr::null()];
66+
unsafe { swap_ptr(&mut ptr0, &mut ptr1); };
67+
68+
assert_eq!(unsafe { *ptr1 }, x);
69+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#include <stddef.h>
2+
3+
// See comments in build_native_lib()
4+
#define EXPORT __attribute__((visibility("default")))
5+
6+
/* Test: test_modify_int */
7+
8+
EXPORT void modify_int(int *ptr) {
9+
*ptr += 2;
10+
}
11+
12+
/* Test: test_init_int */
13+
14+
EXPORT void init_int(int *ptr) {
15+
*ptr = 29;
16+
}
17+
18+
/* Test: test_init_array */
19+
20+
EXPORT void init_array(int *array, size_t len, int value) {
21+
for (size_t i = 0; i < len; i++) {
22+
array[i] = value;
23+
}
24+
}
25+
26+
/* Test: test_swap_ptr */
27+
28+
EXPORT void swap_ptr(const int **x, const int **y) {
29+
const int *tmp = *x;
30+
*x = *y;
31+
*y = tmp;
32+
}

src/tools/miri/tests/ui.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ fn build_native_lib() -> PathBuf {
6464
// FIXME: Automate gathering of all relevant C source files in the directory.
6565
"tests/native-lib/scalar_arguments.c",
6666
"tests/native-lib/ptr_read_access.c",
67+
"tests/native-lib/ptr_write_access.c",
6768
// Ensure we notice serious problems in the C code.
6869
"-Wall",
6970
"-Wextra",

0 commit comments

Comments
 (0)