Skip to content

Commit 733deeb

Browse files
committed
try document prepare_for_native_call, fix BorrowMutError in expose_ptr, overhaul ptr_write_access tests, refactor ptr_read_access, fix typo
1 parent dc693ff commit 733deeb

File tree

7 files changed

+184
-73
lines changed

7 files changed

+184
-73
lines changed

compiler/rustc_const_eval/src/interpret/machine.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ pub trait Machine<'tcx>: Sized {
327327
addr: u64,
328328
) -> InterpResult<'tcx, Pointer<Option<Self::Provenance>>>;
329329

330-
/// Marks a pointer as exposed, allowing it's provenance
330+
/// Marks a pointer as exposed, allowing its provenance
331331
/// to be recovered. "Pointer-to-int cast"
332332
fn expose_provenance(
333333
ecx: &InterpCx<'tcx, Self>,

compiler/rustc_const_eval/src/interpret/memory.rs

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

947+
/// Handle the effect an FFI call might have on the state of allocations.
948+
/// This overapproximates the modifications which external code might make to memory:
949+
/// We set all reachable allocations as initialized, mark all provenances as exposed
950+
/// and overwrite them with `Provenance::WILDCARD`.
947951
pub fn prepare_for_native_call(
948952
&mut self,
949953
id: AllocId,

src/tools/miri/src/alloc_addresses/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
300300
}
301301
trace!("Exposing allocation id {alloc_id:?}");
302302
global_state.exposed.insert(alloc_id);
303+
drop(global_state);
303304
if this.machine.borrow_tracker.is_some() {
304305
this.expose_tag(alloc_id, tag)?;
305306
}

src/tools/miri/tests/native-lib/pass/ptr_read_access.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,17 @@
33
//@only-on-host
44

55
fn main() {
6-
test_pointer();
6+
test_access_pointer();
77

8-
test_simple();
8+
test_access_simple();
99

10-
test_nested();
10+
test_access_nested();
1111

12-
test_static();
12+
test_access_static();
1313
}
1414

15-
// Test void function that dereferences a pointer and prints its contents from C.
16-
fn test_pointer() {
15+
// Test function that dereferences an int pointer and prints its contents from C.
16+
fn test_access_pointer() {
1717
extern "C" {
1818
fn print_pointer(ptr: *const i32);
1919
}
@@ -24,7 +24,7 @@ fn test_pointer() {
2424
}
2525

2626
// Test function that dereferences a simple struct pointer and accesses a field.
27-
fn test_simple() {
27+
fn test_access_simple() {
2828
#[repr(C)]
2929
struct Simple {
3030
field: i32,
@@ -40,7 +40,7 @@ fn test_simple() {
4040
}
4141

4242
// Test function that dereferences nested struct pointers and accesses fields.
43-
fn test_nested() {
43+
fn test_access_nested() {
4444
use std::ptr::NonNull;
4545

4646
#[derive(Debug, PartialEq, Eq)]
@@ -61,8 +61,8 @@ fn test_nested() {
6161
assert_eq!(unsafe { access_nested(&nested_2) }, 97);
6262
}
6363

64-
// Test function that dereferences static struct pointers and accesses fields.
65-
fn test_static() {
64+
// Test function that dereferences a static struct pointer and accesses fields.
65+
fn test_access_static() {
6666
#[repr(C)]
6767
struct Static {
6868
value: i32,

src/tools/miri/tests/native-lib/pass/ptr_write_access.rs

Lines changed: 117 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -5,118 +5,192 @@
55
#![feature(box_as_ptr)]
66

77
use std::mem::MaybeUninit;
8+
use std::ptr::null;
89

910
fn main() {
10-
test_modify_int();
11+
test_increment_int();
1112

1213
test_init_int();
1314

1415
test_init_array();
1516

16-
test_init_interior_mutable();
17+
test_init_static_inner();
18+
19+
test_expose_int();
1720

1821
test_swap_ptr();
1922

20-
test_interact_dangling();
23+
test_swap_nested_ptr();
24+
25+
test_swap_tuple();
26+
27+
test_overwrite_dangling();
2128

22-
test_inner_alloc_exposed();
29+
test_expose_triple();
2330
}
2431

25-
fn test_modify_int() {
32+
// Test function that modifies an int.
33+
fn test_increment_int() {
2634
extern "C" {
27-
fn modify_int(ptr: *mut i32);
35+
fn increment_int(ptr: *mut i32);
2836
}
2937

3038
let mut x = 11;
31-
unsafe { modify_int(&mut x) };
3239

40+
unsafe { increment_int(&mut x) };
3341
assert_eq!(x, 12);
3442
}
3543

44+
// Test function that initializes an int.
3645
fn test_init_int() {
3746
extern "C" {
38-
fn init_int(ptr: *mut i32);
47+
fn init_int(ptr: *mut i32, val: i32);
3948
}
4049

4150
let mut x = MaybeUninit::<i32>::uninit();
51+
let val = 21;
52+
4253
let x = unsafe {
43-
init_int(x.as_mut_ptr());
54+
init_int(x.as_mut_ptr(), val);
4455
x.assume_init()
4556
};
46-
47-
assert_eq!(x, 21);
57+
assert_eq!(x, val);
4858
}
4959

60+
// Test function that initializes an array.
5061
fn test_init_array() {
5162
extern "C" {
52-
fn init_array(ptr: *mut i32, len: usize);
63+
fn init_array(ptr: *mut i32, len: usize, val: i32);
5364
}
5465

5566
const LEN: usize = 3;
56-
5767
let mut array = MaybeUninit::<[i32; LEN]>::uninit();
68+
let val = 31;
69+
5870
let array = unsafe {
59-
init_array(array.as_mut_ptr().cast::<i32>(), LEN);
71+
init_array(array.as_mut_ptr().cast::<i32>(), LEN, val);
6072
array.assume_init()
6173
};
62-
63-
assert_eq!(array, [31; LEN]);
74+
assert_eq!(array, [val; LEN]);
6475
}
6576

66-
fn test_init_interior_mutable() {
77+
// Test function that initializes an int pointed to by an immutable static.
78+
fn test_init_static_inner() {
79+
#[repr(C)]
80+
struct SyncPtr {
81+
ptr: *mut i32
82+
}
83+
unsafe impl Sync for SyncPtr {}
84+
6785
extern "C" {
68-
fn init_interior_mutable(pptr: *const UnsafeInterior);
86+
fn init_static_inner(s_ptr: *const SyncPtr, val: i32);
6987
}
7088

71-
#[repr(C)]
72-
struct UnsafeInterior {
73-
mut_ptr: *mut i32
89+
static mut INNER: MaybeUninit<i32> = MaybeUninit::uninit();
90+
#[allow(static_mut_refs)]
91+
static STATIC: SyncPtr = SyncPtr { ptr: unsafe { INNER.as_mut_ptr() } };
92+
let val = 41;
93+
94+
let inner = unsafe {
95+
init_static_inner(&STATIC, val);
96+
INNER.assume_init()
97+
};
98+
assert_eq!(inner, val);
99+
}
100+
101+
// Test function that writes a pointer and exposes the alloc of its int argument.
102+
fn test_expose_int() {
103+
extern "C" {
104+
fn expose_int(int_ptr: *const i32, pptr: *mut *const i32);
74105
}
75-
unsafe impl Sync for UnsafeInterior {}
76-
77-
let mut x = MaybeUninit::<i32>::uninit();
78-
let unsafe_interior = UnsafeInterior { mut_ptr: x.as_mut_ptr() };
79-
unsafe { init_interior_mutable(&unsafe_interior) };
80106

81-
assert_eq!(unsafe { x.assume_init() }, 51);
107+
let x = 51;
108+
let mut ptr = std::ptr::null();
109+
110+
unsafe { expose_int(&x, &mut ptr) };
111+
assert_eq!(unsafe { *ptr }, x);
82112
}
83113

114+
// Test function that swaps two pointers and exposes the alloc of an int.
84115
fn test_swap_ptr() {
85116
extern "C" {
86117
fn swap_ptr(pptr0: *mut *const i32, pptr1: *mut *const i32);
87118
}
88119

89-
let x = 41;
90-
let mut ptr0 = &raw const x;
91-
let mut ptr1 = std::ptr::null();
120+
let x = 61;
121+
let (mut ptr0, mut ptr1) = (&raw const x, null());
122+
92123
unsafe { swap_ptr(&mut ptr0, &mut ptr1) };
124+
assert_eq!(unsafe { *ptr1 }, x);
125+
}
126+
127+
// Test function that swaps two nested pointers and exposes the alloc of an int.
128+
fn test_swap_nested_ptr() {
129+
extern "C" {
130+
fn swap_nested_ptr(ppptr0: *mut *mut *const i32, ppptr1: *mut *mut *const i32);
131+
}
132+
133+
let x = 71;
134+
let (mut ptr0, mut ptr1) = (&raw const x, null());
135+
let (mut pptr0, mut pptr1) = (&raw mut ptr0, &raw mut ptr1);
93136

137+
unsafe { swap_nested_ptr(&mut pptr0, &mut pptr1) }
94138
assert_eq!(unsafe { *ptr1 }, x);
95139
}
96140

97-
fn test_interact_dangling() {
141+
// Test function that swaps two pointers in a struct and exposes the alloc of an int.
142+
fn test_swap_tuple() {
143+
#[repr(C)]
144+
struct Tuple {
145+
ptr0: *const i32,
146+
ptr1: *const i32,
147+
}
148+
149+
extern "C" {
150+
fn swap_tuple(t_ptr: *mut Tuple);
151+
}
152+
153+
let x = 81;
154+
let mut tuple = Tuple { ptr0: &raw const x, ptr1: null() };
155+
156+
unsafe { swap_tuple(&mut tuple) }
157+
assert_eq!(unsafe { *tuple.ptr1 }, x);
158+
}
159+
160+
// Test function that interacts with a dangling pointer.
161+
fn test_overwrite_dangling() {
98162
extern "C" {
99163
fn overwrite_ptr(pptr: *mut *const i32);
100164
}
101165

102-
let x = Box::new(61);
103-
let mut ptr = Box::as_ptr(&x);
104-
drop(x);
166+
let b = Box::new(91);
167+
let mut ptr = Box::as_ptr(&b);
168+
drop(b);
105169
unsafe { overwrite_ptr(&mut ptr) };
106170

107-
assert_eq!(ptr, std::ptr::null());
171+
assert_eq!(ptr, null());
108172
}
109173

110-
// TODO: Write tests for correctly exposing: [initial allocation; recursively all allocations; previously unexposed pointers].
111-
fn test_inner_alloc_exposed() {
174+
// Test function that interacts with a struct storing a dangling pointer.
175+
fn test_expose_triple() {
176+
#[repr(C)]
177+
struct Triple {
178+
ptr0: *const i32,
179+
ptr1: *const i32,
180+
ptr2: *const i32,
181+
}
182+
112183
extern "C" {
113-
fn blackbox(ptr: *mut *mut *const i32);
184+
fn expose_triple(t_ptr: *const Triple);
114185
}
115186

116-
let x = 71i32;
117-
let mut ptr = &raw const x;
118-
let mut pptr = &raw mut ptr;
119-
unsafe { blackbox(&mut pptr) }
187+
let x = 101;
188+
let y = 111;
189+
let b = Box::new(121);
190+
let ptr = Box::as_ptr(&b);
191+
drop(b);
192+
let triple = Triple { ptr0: &raw const x, ptr1: ptr, ptr2: &raw const y };
120193

121-
assert_eq!(unsafe { *ptr }, x);
194+
unsafe { expose_triple(&triple) }
195+
assert_eq!(unsafe { *triple.ptr2 }, y);
122196
}

src/tools/miri/tests/native-lib/ptr_read_access.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@
33
// See comments in build_native_lib()
44
#define EXPORT __attribute__((visibility("default")))
55

6-
/* Test: test_pointer */
6+
/* Test: test_access_pointer */
77

88
EXPORT void print_pointer(const int *ptr) {
99
printf("printing pointer dereference from C: %d\n", *ptr);
1010
}
1111

12-
/* Test: test_simple */
12+
/* Test: test_access_simple */
1313

1414
typedef struct Simple {
1515
int field;
@@ -19,7 +19,7 @@ EXPORT int access_simple(const Simple *s_ptr) {
1919
return s_ptr->field;
2020
}
2121

22-
/* Test: test_nested */
22+
/* Test: test_access_nested */
2323

2424
typedef struct Nested {
2525
int value;
@@ -38,7 +38,7 @@ EXPORT int access_nested(const Nested *n_ptr) {
3838
return n_ptr->value;
3939
}
4040

41-
/* Test: test_static */
41+
/* Test: test_access_static */
4242

4343
typedef struct Static {
4444
int value;

0 commit comments

Comments
 (0)