Skip to content

Commit dcdb101

Browse files
committed
refactor and expand native-lib tests, comment fixes
1 parent 7bdec46 commit dcdb101

File tree

9 files changed

+160
-20
lines changed

9 files changed

+160
-20
lines changed

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

+4-2
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
197197
AllocKind::Function | AllocKind::VTable => {
198198
// Allocate some dummy memory to get a unique address for this function/vtable.
199199
let alloc_bytes = MiriAllocBytes::from_bytes(&[0u8; 1], Align::from_bytes(1).unwrap());
200+
// We don't need to expose these bytes as nobody is allowed to access them.
200201
let addr = alloc_bytes.as_ptr().addr().try_into().unwrap();
201202
// Leak the underlying memory to ensure it remains unique.
202203
std::mem::forget(alloc_bytes);
@@ -372,10 +373,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
372373
.prepared_alloc_bytes
373374
.remove(&id)
374375
.unwrap_or_else(|| panic!("alloc bytes for {id:?} have not been prepared"));
376+
// Sanity-check that the prepared allocation has the right size and alignment.
375377
assert!(prepared_alloc_bytes.as_ptr().is_aligned_to(align.bytes_usize()));
376378
assert_eq!(prepared_alloc_bytes.len(), bytes.len());
377-
// SAFETY: `alloc_bytes` and `bytes` span the same number of bytes.
378-
unsafe { prepared_alloc_bytes.as_mut_ptr().copy_from(bytes.as_ptr(), bytes.len()) };
379+
// Copy allocation contents into prepared memory.
380+
prepared_alloc_bytes.copy_from_slice(bytes);
379381
prepared_alloc_bytes
380382
} else {
381383
MiriAllocBytes::from_bytes(std::borrow::Cow::Borrowed(&*bytes), align)
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,20 @@
11
CODEABI_1.0 {
22
# Define which symbols to export.
33
global:
4+
# scalar_arguments.c
45
add_one_int;
56
printer;
6-
ptr_printer;
77
test_stack_spill;
88
get_unsigned_int;
99
add_int16;
1010
add_short_to_long;
11+
12+
# ptr_read_access.c
13+
print_pointer;
14+
access_simple;
15+
access_nested;
16+
access_static;
17+
1118
# The rest remains private.
1219
local: *;
13-
};
20+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
//@only-target-linux
2+
//@only-on-host
3+
4+
fn main() {
5+
test_pointer();
6+
7+
test_simple();
8+
9+
test_nested();
10+
11+
test_static();
12+
}
13+
14+
// Test function that dereferences a pointer and prints its contents from C.
15+
fn test_pointer() {
16+
extern "C" {
17+
fn print_pointer(ptr: *mut i32);
18+
}
19+
20+
let mut x = 42;
21+
let ptr = &mut x as *mut i32;
22+
23+
unsafe { print_pointer(ptr) };
24+
}
25+
26+
// Test function that dereferences a simple struct pointer and accesses a field.
27+
fn test_simple() {
28+
#[repr(C)]
29+
struct Simple {
30+
field: i32
31+
}
32+
33+
extern "C" {
34+
fn access_simple(s_ptr: *mut Simple) -> i32;
35+
}
36+
37+
let mut simple = Simple { field: -42 };
38+
let s_ptr = &mut simple as *mut Simple;
39+
40+
let result = unsafe { access_simple(s_ptr) };
41+
assert_eq!(result, -42);
42+
}
43+
44+
// Test function that dereferences nested struct pointers and accesses fields.
45+
fn test_nested() {
46+
use std::ptr::NonNull;
47+
48+
#[derive(Debug, PartialEq, Eq)]
49+
#[repr(C)]
50+
struct Nested {
51+
value: i32,
52+
next: Option<NonNull<Nested>>,
53+
}
54+
55+
extern "C" {
56+
fn access_nested(n_ptr: *mut Nested) -> i32;
57+
}
58+
59+
let mut nested_0 = Nested { value: 0, next: None };
60+
let mut nested_1 = Nested { value: 1, next: NonNull::new(&mut nested_0) };
61+
let mut nested_2 = Nested { value: 2, next: NonNull::new(&mut nested_1) };
62+
let mut nested_3 = Nested { value: 3, next: NonNull::new(&mut nested_2) };
63+
let n_ptr = &mut nested_3 as *mut Nested;
64+
65+
let result = unsafe { access_nested(n_ptr) };
66+
assert_eq!(result, 0);
67+
}
68+
69+
// Test function that dereferences static struct pointers and accesses fields.
70+
fn test_static() {
71+
72+
#[repr(C)]
73+
struct Static {
74+
value: i32,
75+
recurse: &'static Static,
76+
}
77+
78+
extern "C" {
79+
fn access_static(n_ptr: *const Static) -> i32;
80+
}
81+
82+
static STATIC: Static = Static {
83+
value: 9001,
84+
recurse: &STATIC,
85+
};
86+
87+
let result = unsafe { access_static(&STATIC) };
88+
assert_eq!(result, 9001);
89+
}
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
1-
printing from C
21
printing pointer dereference from C: 42

src/tools/miri/tests/native-lib/pass/call_extern_c_fn.rs renamed to src/tools/miri/tests/native-lib/pass/scalar_arguments.rs

+1-7
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ extern "C" {
2121
fn add_short_to_long(x: i16, y: i64) -> i64;
2222
fn get_unsigned_int() -> u32;
2323
fn printer();
24-
fn ptr_printer(ptr: *mut i32);
2524
}
2625

2726
fn main() {
@@ -43,10 +42,5 @@ fn main() {
4342

4443
// test void function that prints from C
4544
printer();
46-
47-
// test void function that dereferences a pointer and prints its contents from C
48-
let mut x = 42i32;
49-
let ptr = &mut x as *mut i32;
50-
ptr_printer(ptr);
5145
}
52-
}
46+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
printing from C
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#include <stdio.h>
2+
3+
/* Test. */
4+
5+
void print_pointer(int *ptr) {
6+
printf("printing pointer dereference from C: %d\n", *ptr);
7+
}
8+
9+
/* Test. */
10+
11+
typedef struct Simple {
12+
int field;
13+
} Simple;
14+
15+
int access_simple(Simple *s_ptr) {
16+
return s_ptr->field;
17+
}
18+
19+
/* Test. */
20+
21+
typedef struct Nested {
22+
int value;
23+
struct Nested *next;
24+
} Nested;
25+
26+
// Returns the innermost/last `value` of the `Nested` pointer chain.
27+
int access_nested(Nested *n_ptr) {
28+
// Edge case: `n_ptr == NULL`, first Nested is None).
29+
if (!n_ptr) { return 0; }
30+
31+
while (n_ptr->next) {
32+
n_ptr = n_ptr->next;
33+
}
34+
35+
return n_ptr->value;
36+
}
37+
38+
/* Test. */
39+
40+
typedef struct Static {
41+
int value;
42+
struct Static *recurse;
43+
} Static;
44+
45+
int access_static(Static *s_ptr) {
46+
return s_ptr->recurse->recurse->value;
47+
}

src/tools/miri/tests/native-lib/test.c renamed to src/tools/miri/tests/native-lib/scalar_arguments.c

+1-5
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,6 @@ void printer() {
88
printf("printing from C\n");
99
}
1010

11-
void ptr_printer(int *ptr) {
12-
printf("printing pointer dereference from C: %d\n", *ptr);
13-
}
14-
1511
// function with many arguments, to test functionality when some args are stored
1612
// on the stack
1713
int test_stack_spill(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l) {
@@ -28,4 +24,4 @@ short add_int16(short x) {
2824

2925
long add_short_to_long(short x, long y) {
3026
return x + y;
31-
}
27+
}

src/tools/miri/tests/ui.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -36,18 +36,23 @@ fn build_native_lib() -> PathBuf {
3636
// Create the directory if it does not already exist.
3737
std::fs::create_dir_all(&so_target_dir)
3838
.expect("Failed to create directory for shared object file");
39-
let so_file_path = so_target_dir.join("libtestlib.so");
39+
/*let so_file_path = so_target_dir.join("scalar_arguments.so");*/
40+
let so_file_path = so_target_dir.join(format!("native-lib.so"));
4041
let cc_output = Command::new(cc)
4142
.args([
4243
"-shared",
4344
"-o",
4445
so_file_path.to_str().unwrap(),
45-
"tests/native-lib/test.c",
46+
&format!("tests/native-lib/scalar_arguments.c"),
47+
&format!("tests/native-lib/ptr_read_access.c"),
4648
// Only add the functions specified in libcode.version to the shared object file.
4749
// This is to avoid automatically adding `malloc`, etc.
4850
// Source: https://anadoxin.org/blog/control-over-symbol-exports-in-gcc.html/
4951
"-fPIC",
50-
"-Wl,--version-script=tests/native-lib/libtest.map",
52+
&format!("-Wl,--version-script=tests/native-lib/native-lib.map"),
53+
"-Werror",
54+
"-Wextra",
55+
"-Wpedantic",
5156
])
5257
.output()
5358
.expect("failed to generate shared object file for testing native function calls");

0 commit comments

Comments
 (0)