Skip to content

Commit 2782030

Browse files
committed
Failed attempt: shouldn't directly write a u64 for eventfd pointer mplace
1 parent d4377b5 commit 2782030

File tree

4 files changed

+51
-14
lines changed

4 files changed

+51
-14
lines changed

src/shims/unix/fd.rs

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ pub trait FileDescription: std::fmt::Debug + Any {
3131
_self_ref: &FileDescriptionRef,
3232
_communicate_allowed: bool,
3333
_bytes: &mut [u8],
34+
_len: usize,
3435
_ptr: Pointer,
3536
_dest: &MPlaceTy<'tcx>,
3637
_ecx: &mut MiriInterpCx<'tcx>,
@@ -132,6 +133,7 @@ impl FileDescription for io::Stdin {
132133
_self_ref: &FileDescriptionRef,
133134
communicate_allowed: bool,
134135
bytes: &mut [u8],
136+
_len: usize,
135137
ptr: Pointer,
136138
dest: &MPlaceTy<'tcx>,
137139
ecx: &mut MiriInterpCx<'tcx>,
@@ -583,9 +585,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
583585
// because it was a target's `usize`. Also we are sure that its smaller than
584586
// `usize::MAX` because it is bounded by the host's `isize`.
585587

586-
let mut bytes = vec![0; usize::try_from(count).unwrap()];
588+
let len = usize::try_from(count).unwrap();
589+
let mut bytes = vec![0; len];
587590
match offset {
588-
None => fd.read(&fd, communicate, &mut bytes, buf, dest, this)?,
591+
None => fd.read(&fd, communicate, &mut bytes, len, buf, dest, this)?,
589592
Some(offset) => {
590593
let Ok(offset) = u64::try_from(offset) else {
591594
let einval = this.eval_libc("EINVAL");
@@ -679,6 +682,39 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
679682
}
680683
}
681684

685+
686+
/// This function either writes to the user supplied buffer and to dest place, or return error.
687+
// TODO: this is only used for eventfd
688+
fn read_byte_helper_ev(
689+
&mut self,
690+
buf_place: &MPlaceTy<'tcx>,
691+
read_val: Option<u64>,
692+
result: io::Result<usize>,
693+
dest: &MPlaceTy<'tcx>,
694+
) -> InterpResult<'tcx> {
695+
let this = self.eval_context_mut();
696+
// `File::read` never returns a value larger than `count`, so this cannot fail.
697+
match result.map(|c| i64::try_from(c).unwrap()) {
698+
// try to pass this the write_ptr inside write
699+
// Pass the pointer inside the write function.
700+
Ok(read_bytes) => {
701+
// If reading to `bytes` did not fail, we write those bytes to the buffer.
702+
// Crucially, if fewer than `bytes.len()` bytes were read, only write
703+
// that much into the output buffer!
704+
// Write to the user supplied buffer.
705+
this.write_int(read_val.unwrap(), buf_place)?;
706+
// Write to the function return value place.
707+
this.write_int(read_bytes, dest)?;
708+
return Ok(());
709+
}
710+
Err(e) => {
711+
this.set_last_error_from_io_error(e)?;
712+
this.write_int(-1, dest)?;
713+
return Ok(());
714+
}
715+
}
716+
}
717+
682718
/// This function either writes the number of written bytes to dest place or return error.
683719
fn write_byte_helper(
684720
&mut self,

src/shims/unix/fs.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ impl FileDescription for FileHandle {
3535
_self_ref: &FileDescriptionRef,
3636
communicate_allowed: bool,
3737
bytes: &mut [u8],
38+
_len: usize,
3839
ptr: Pointer,
3940
dest: &MPlaceTy<'tcx>,
4041
ecx: &mut MiriInterpCx<'tcx>,

src/shims/unix/linux/eventfd.rs

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -62,23 +62,27 @@ impl FileDescription for Event {
6262
&self,
6363
self_ref: &FileDescriptionRef,
6464
_communicate_allowed: bool,
65-
bytes: &mut [u8],
65+
_bytes: &mut [u8],
66+
len: usize,
6667
ptr: Pointer,
6768
dest: &MPlaceTy<'tcx>,
6869
ecx: &mut MiriInterpCx<'tcx>,
6970
) -> InterpResult<'tcx> {
71+
// eventfd read at the size of u64.
72+
let buf_place = ecx.ptr_to_mplace(ptr, ecx.machine.layouts.u64);
7073
// Check the size of slice, and return error only if the size of the slice < 8.
71-
let Some(bytes) = bytes.first_chunk_mut::<U64_ARRAY_SIZE>() else {
74+
if len < U64_ARRAY_SIZE {
7275
let result = Err(Error::from(ErrorKind::InvalidInput));
73-
ecx.read_byte_helper(ptr, bytes.to_vec(), result, dest)?;
76+
ecx.read_byte_helper_ev(&buf_place, None, result, dest)?;
7477
return Ok(());
75-
};
78+
}
79+
7680
// Block when counter == 0.
7781
let counter = self.counter.get();
7882
if counter == 0 {
7983
if self.is_nonblock {
8084
let result = Err(Error::from(ErrorKind::WouldBlock));
81-
ecx.read_byte_helper(ptr, bytes.to_vec(), result, dest)?;
85+
ecx.read_byte_helper_ev(&buf_place, None, result, dest)?;
8286
return Ok(());
8387
} else {
8488
//FIXME: blocking is not supported
@@ -87,18 +91,13 @@ impl FileDescription for Event {
8791
} else {
8892
// Synchronize with all prior `write` calls to this FD.
8993
ecx.acquire_clock(&self.clock.borrow());
90-
// Return the counter in the host endianness using the buffer provided by caller.
91-
*bytes = match ecx.tcx.sess.target.endian {
92-
Endian::Little => counter.to_le_bytes(),
93-
Endian::Big => counter.to_be_bytes(),
94-
};
94+
let result = Ok(U64_ARRAY_SIZE);
95+
ecx.read_byte_helper_ev(&buf_place, Some(counter), result, dest)?;
9596
self.counter.set(0);
9697
// When any of the event happened, we check and update the status of all supported event
9798
// types for current file description.
9899
ecx.check_and_update_readiness(self_ref)?;
99100

100-
let result = Ok(U64_ARRAY_SIZE);
101-
ecx.read_byte_helper(ptr, bytes.to_vec(), result, dest)?;
102101
return Ok(());
103102
}
104103
}

src/shims/unix/unnamed_socket.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ impl FileDescription for AnonSocket {
127127
_self_ref: &FileDescriptionRef,
128128
_communicate_allowed: bool,
129129
bytes: &mut [u8],
130+
_len: usize,
130131
ptr: Pointer,
131132
dest: &MPlaceTy<'tcx>,
132133
ecx: &mut MiriInterpCx<'tcx>,

0 commit comments

Comments
 (0)