Skip to content

Commit e831174

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

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>,
@@ -584,9 +586,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
584586
// because it was a target's `usize`. Also we are sure that its smaller than
585587
// `usize::MAX` because it is bounded by the host's `isize`.
586588

587-
let mut bytes = vec![0; usize::try_from(count).unwrap()];
589+
let len = usize::try_from(count).unwrap();
590+
let mut bytes = vec![0; len];
588591
match offset {
589-
None => fd.read(&fd, communicate, &mut bytes, buf, dest, this)?,
592+
None => fd.read(&fd, communicate, &mut bytes, len, buf, dest, this)?,
590593
Some(offset) => {
591594
let Ok(offset) = u64::try_from(offset) else {
592595
let einval = this.eval_libc("EINVAL");
@@ -677,6 +680,39 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
677680
}
678681
}
679682

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