Skip to content

Commit db73863

Browse files
committed
Auto merge of rust-lang#2857 - RalfJung:endian, r=RalfJung
fix endianess handling in eventfd::write Fixes rust-lang/miri#2800
2 parents 9f22b37 + 99e3034 commit db73863

File tree

2 files changed

+26
-8
lines changed

2 files changed

+26
-8
lines changed

src/tools/miri/src/shims/unix/fs.rs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use std::time::SystemTime;
1111
use log::trace;
1212

1313
use rustc_data_structures::fx::FxHashMap;
14+
use rustc_middle::ty::TyCtxt;
1415
use rustc_target::abi::{Align, Size};
1516

1617
use crate::shims::os_str::bytes_to_os_str;
@@ -31,6 +32,7 @@ pub trait FileDescriptor: std::fmt::Debug + helpers::AsAny {
3132
&mut self,
3233
_communicate_allowed: bool,
3334
_bytes: &mut [u8],
35+
_tcx: TyCtxt<'tcx>,
3436
) -> InterpResult<'tcx, io::Result<usize>> {
3537
throw_unsup_format!("cannot read from {}", self.name());
3638
}
@@ -39,6 +41,7 @@ pub trait FileDescriptor: std::fmt::Debug + helpers::AsAny {
3941
&self,
4042
_communicate_allowed: bool,
4143
_bytes: &[u8],
44+
_tcx: TyCtxt<'tcx>,
4245
) -> InterpResult<'tcx, io::Result<usize>> {
4346
throw_unsup_format!("cannot write to {}", self.name());
4447
}
@@ -79,6 +82,7 @@ impl FileDescriptor for FileHandle {
7982
&mut self,
8083
communicate_allowed: bool,
8184
bytes: &mut [u8],
85+
_tcx: TyCtxt<'tcx>,
8286
) -> InterpResult<'tcx, io::Result<usize>> {
8387
assert!(communicate_allowed, "isolation should have prevented even opening a file");
8488
Ok(self.file.read(bytes))
@@ -88,6 +92,7 @@ impl FileDescriptor for FileHandle {
8892
&self,
8993
communicate_allowed: bool,
9094
bytes: &[u8],
95+
_tcx: TyCtxt<'tcx>,
9196
) -> InterpResult<'tcx, io::Result<usize>> {
9297
assert!(communicate_allowed, "isolation should have prevented even opening a file");
9398
Ok((&mut &self.file).write(bytes))
@@ -153,6 +158,7 @@ impl FileDescriptor for io::Stdin {
153158
&mut self,
154159
communicate_allowed: bool,
155160
bytes: &mut [u8],
161+
_tcx: TyCtxt<'tcx>,
156162
) -> InterpResult<'tcx, io::Result<usize>> {
157163
if !communicate_allowed {
158164
// We want isolation mode to be deterministic, so we have to disallow all reads, even stdin.
@@ -184,6 +190,7 @@ impl FileDescriptor for io::Stdout {
184190
&self,
185191
_communicate_allowed: bool,
186192
bytes: &[u8],
193+
_tcx: TyCtxt<'tcx>,
187194
) -> InterpResult<'tcx, io::Result<usize>> {
188195
// We allow writing to stderr even with isolation enabled.
189196
let result = Write::write(&mut { self }, bytes);
@@ -220,6 +227,7 @@ impl FileDescriptor for io::Stderr {
220227
&self,
221228
_communicate_allowed: bool,
222229
bytes: &[u8],
230+
_tcx: TyCtxt<'tcx>,
223231
) -> InterpResult<'tcx, io::Result<usize>> {
224232
// We allow writing to stderr even with isolation enabled.
225233
// No need to flush, stderr is not buffered.
@@ -252,6 +260,7 @@ impl FileDescriptor for NullOutput {
252260
&self,
253261
_communicate_allowed: bool,
254262
bytes: &[u8],
263+
_tcx: TyCtxt<'tcx>,
255264
) -> InterpResult<'tcx, io::Result<usize>> {
256265
// We just don't write anything, but report to the user that we did.
257266
Ok(Ok(bytes.len()))
@@ -756,8 +765,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
756765
let mut bytes = vec![0; usize::try_from(count).unwrap()];
757766
// `File::read` never returns a value larger than `count`,
758767
// so this cannot fail.
759-
let result =
760-
file_descriptor.read(communicate, &mut bytes)?.map(|c| i64::try_from(c).unwrap());
768+
let result = file_descriptor
769+
.read(communicate, &mut bytes, *this.tcx)?
770+
.map(|c| i64::try_from(c).unwrap());
761771

762772
match result {
763773
Ok(read_bytes) => {
@@ -803,8 +813,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
803813

804814
if let Some(file_descriptor) = this.machine.file_handler.handles.get(&fd) {
805815
let bytes = this.read_bytes_ptr_strip_provenance(buf, Size::from_bytes(count))?;
806-
let result =
807-
file_descriptor.write(communicate, bytes)?.map(|c| i64::try_from(c).unwrap());
816+
let result = file_descriptor
817+
.write(communicate, bytes, *this.tcx)?
818+
.map(|c| i64::try_from(c).unwrap());
808819
this.try_unwrap_io_result(result)
809820
} else {
810821
this.handle_not_found()

src/tools/miri/src/shims/unix/linux/fd/event.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use crate::shims::unix::fs::FileDescriptor;
22

33
use rustc_const_eval::interpret::InterpResult;
4+
use rustc_middle::ty::TyCtxt;
5+
use rustc_target::abi::Endian;
46

57
use std::cell::Cell;
68
use std::io;
@@ -36,7 +38,7 @@ impl FileDescriptor for Event {
3638
}
3739

3840
/// A write call adds the 8-byte integer value supplied in
39-
/// its buffer to the counter. The maximum value that may be
41+
/// its buffer (in native endianess) to the counter. The maximum value that may be
4042
/// stored in the counter is the largest unsigned 64-bit value
4143
/// minus 1 (i.e., 0xfffffffffffffffe). If the addition would
4244
/// cause the counter's value to exceed the maximum, then the
@@ -47,17 +49,22 @@ impl FileDescriptor for Event {
4749
/// A write fails with the error EINVAL if the size of the
4850
/// supplied buffer is less than 8 bytes, or if an attempt is
4951
/// made to write the value 0xffffffffffffffff.
50-
///
51-
/// FIXME: use endianness
5252
fn write<'tcx>(
5353
&self,
5454
_communicate_allowed: bool,
5555
bytes: &[u8],
56+
tcx: TyCtxt<'tcx>,
5657
) -> InterpResult<'tcx, io::Result<usize>> {
5758
let v1 = self.val.get();
59+
let bytes: [u8; 8] = bytes.try_into().unwrap(); // FIXME fail gracefully when this has the wrong size
60+
// Convert from target endianess to host endianess.
61+
let num = match tcx.sess.target.endian {
62+
Endian::Little => u64::from_le_bytes(bytes),
63+
Endian::Big => u64::from_be_bytes(bytes),
64+
};
5865
// FIXME handle blocking when addition results in exceeding the max u64 value
5966
// or fail with EAGAIN if the file descriptor is nonblocking.
60-
let v2 = v1.checked_add(u64::from_be_bytes(bytes.try_into().unwrap())).unwrap();
67+
let v2 = v1.checked_add(num).unwrap();
6168
self.val.set(v2);
6269
assert_eq!(8, bytes.len());
6370
Ok(Ok(8))

0 commit comments

Comments
 (0)