Skip to content

Commit dacfe9c

Browse files
committed
Add more pass test and race test
1 parent a080f8c commit dacfe9c

File tree

2 files changed

+100
-17
lines changed

2 files changed

+100
-17
lines changed

src/shims/unix/linux/eventfd.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ impl FileDescription for Event {
4949
ecx: &mut MiriInterpCx<'tcx>,
5050
) -> InterpResult<'tcx, io::Result<usize>> {
5151
// Check the size of slice, and return error only if the size of the slice < 8.
52-
if <[u8; 8]>::try_from(&bytes[0..8]).is_err() {
52+
if bytes.first_chunk::<8>().is_none() {
5353
return Ok(Err(Error::from(ErrorKind::InvalidInput)));
5454
}
5555
if self.counter == 0 {
@@ -65,7 +65,8 @@ impl FileDescription for Event {
6565
Endian::Little => self.counter.to_le_bytes(),
6666
Endian::Big => self.counter.to_be_bytes(),
6767
};
68-
bytes.copy_from_slice(&counter_byte);
68+
// Use bytes[0..8] to prevent panic when size of bytes > 8.
69+
bytes[0..8].copy_from_slice(&counter_byte);
6970
self.counter = 0;
7071
return Ok(Ok(8));
7172
}
@@ -89,17 +90,17 @@ impl FileDescription for Event {
8990
bytes: &[u8],
9091
ecx: &mut MiriInterpCx<'tcx>,
9192
) -> InterpResult<'tcx, io::Result<usize>> {
92-
let bytes = match bytes[0..8].try_into() {
93-
Ok(bytes) => bytes,
94-
Err(_) => {
95-
// Size of bytes is less than 8.
93+
// Check the size of slice, and return error only if the size of the slice < 8.
94+
let bytes = match bytes.first_chunk::<8>() {
95+
Some(bytes) => bytes,
96+
None => {
9697
return Ok(Err(Error::from(ErrorKind::InvalidInput)));
9798
}
9899
};
99100
// Convert from target endianness to host endianness.
100101
let num = match ecx.tcx.sess.target.endian {
101-
Endian::Little => u64::from_le_bytes(bytes),
102-
Endian::Big => u64::from_be_bytes(bytes),
102+
Endian::Little => u64::from_le_bytes(*bytes),
103+
Endian::Big => u64::from_be_bytes(*bytes),
103104
};
104105
// u64::MAX as input is invalid because the maximum value of counter is u64::MAX - 1.
105106
if num == u64::MAX {

tests/pass-dep/libc/libc-eventfd.rs

Lines changed: 91 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,34 @@
11
//@ignore-target-windows: No eventfd in windows
22

3+
use std::thread;
4+
35
fn main() {
4-
test_read_write();
6+
//test_read_write();
7+
test_race();
58
}
69

710
fn test_read_write() {
811
let flags = libc::EFD_NONBLOCK | libc::EFD_CLOEXEC;
912
let fd = unsafe { libc::eventfd(0, flags) };
10-
let data: [u8; 8];
13+
let sized_8_data: [u8; 8];
1114
if cfg!(target_endian = "big") {
1215
// Adjust the data based on the endianess of host system.
13-
data = [0, 0, 0, 0, 0, 0, 0, 1];
16+
sized_8_data = [0, 0, 0, 0, 0, 0, 0, 1];
1417
} else {
15-
data = [1, 0, 0, 0, 0, 0, 0, 0];
18+
sized_8_data = [1, 0, 0, 0, 0, 0, 0, 0];
1619
}
17-
// Write 1 to the counter
18-
let res: i64 =
19-
unsafe { libc::write(fd, data.as_ptr() as *const libc::c_void, 8).try_into().unwrap() };
20+
// Write 1 to the counter.
21+
let res: i64 = unsafe {
22+
libc::write(fd, sized_8_data.as_ptr() as *const libc::c_void, 8).try_into().unwrap()
23+
};
2024
assert_eq!(res, 8);
2125

22-
// Read 1 from the counter
26+
// Read 1 from the counter.
2327
let mut buf: [u8; 8] = [1; 8];
2428
let res: i32 = unsafe {
2529
libc::read(fd, buf.as_mut_ptr().cast(), buf.len() as libc::size_t).try_into().unwrap()
2630
};
27-
// read returns number of bytes has been read, which is always 8
31+
// Read returns number of bytes has been read, which is always 8.
2832
assert_eq!(res, 8);
2933
let counter: u64;
3034
if cfg!(target_endian = "big") {
@@ -34,4 +38,82 @@ fn test_read_write() {
3438
counter = u64::from_le_bytes(buf);
3539
}
3640
assert_eq!(counter, 1);
41+
42+
// Write with buffer size > 8 bytes.
43+
let res: i64 = unsafe {
44+
libc::write(fd, sized_8_data.as_ptr() as *const libc::c_void, 8).try_into().unwrap()
45+
};
46+
assert_eq!(res, 8);
47+
48+
// Read with supplied buffer that < 8 bytes.
49+
let mut buf: [u8; 7] = [1; 7];
50+
let res: i32 = unsafe {
51+
libc::read(fd, buf.as_mut_ptr().cast(), buf.len() as libc::size_t).try_into().unwrap()
52+
};
53+
assert_eq!(res, -1);
54+
55+
// Write with supplied buffer that < 8 bytes
56+
let res: i64 = unsafe {
57+
libc::write(fd, sized_8_data[0..7].as_ptr() as *const libc::c_void, 7).try_into().unwrap()
58+
};
59+
assert_eq!(res, -1);
60+
61+
// Write with supplied buffer that > 8 bytes
62+
let sized_9_data: [u8; 9];
63+
if cfg!(target_endian = "big") {
64+
// Adjust the data based on the endianess of host system.
65+
sized_9_data = [0, 0, 0, 0, 0, 0, 0, 0, 1];
66+
} else {
67+
sized_9_data = [1, 0, 0, 0, 0, 0, 0, 0, 0];
68+
}
69+
let res: i64 = unsafe {
70+
libc::write(fd, sized_9_data.as_ptr() as *const libc::c_void, 8).try_into().unwrap()
71+
};
72+
assert_eq!(res, 8);
73+
74+
// Read with supplied buffer > 8 bytes.
75+
let mut buf: [u8; 9] = [1; 9];
76+
let res: i32 = unsafe {
77+
libc::read(fd, buf.as_mut_ptr().cast(), buf.len() as libc::size_t).try_into().unwrap()
78+
};
79+
assert_eq!(res, 8);
80+
}
81+
82+
fn test_race() {
83+
static mut VAL: u8 = 0;
84+
let flags = libc::EFD_NONBLOCK | libc::EFD_CLOEXEC;
85+
let fd = unsafe { libc::eventfd(0, flags) };
86+
let thread1 = thread::spawn(move || {
87+
let mut buf: [u8; 8] = [0; 8];
88+
let res: i32 = unsafe {
89+
libc::read(fd, buf.as_mut_ptr().cast(), buf.len() as libc::size_t).try_into().unwrap()
90+
};
91+
// read returns number of bytes has been read, which is always 8
92+
assert_eq!(res, 8);
93+
let counter: u64;
94+
if cfg!(target_endian = "big") {
95+
// Read will store the bytes based on the endianess of the host system.
96+
counter = u64::from_be_bytes(buf);
97+
} else {
98+
counter = u64::from_le_bytes(buf);
99+
}
100+
assert_eq!(counter, 1);
101+
// Read from the static mutable variable
102+
unsafe { assert_eq!(VAL, 1) };
103+
});
104+
// Write to the static mutable variable
105+
unsafe { VAL = 1 };
106+
let data: [u8; 8];
107+
if cfg!(target_endian = "big") {
108+
// Adjust the data based on the endianess of host system.
109+
data = [0, 0, 0, 0, 0, 0, 0, 1];
110+
} else {
111+
data = [1, 0, 0, 0, 0, 0, 0, 0];
112+
}
113+
let res: i64 =
114+
unsafe { libc::write(fd, data.as_ptr() as *const libc::c_void, 8).try_into().unwrap() };
115+
// write return number of bytes written, which is always 8
116+
assert_eq!(res, 8);
117+
thread::yield_now();
118+
thread1.join().unwrap();
37119
}

0 commit comments

Comments
 (0)