diff options
| author | Ralf Jung <post@ralfj.de> | 2023-04-26 15:42:06 +0200 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2023-04-26 15:42:14 +0200 |
| commit | 99e3034bd2dc400a15063a347d322b43dcf63e2d (patch) | |
| tree | 8885ac852269946102926750e8665ff306a6e3ae | |
| parent | 9f22b37f7b500ee69d851d140a9feb83bcfb1d00 (diff) | |
| download | rust-99e3034bd2dc400a15063a347d322b43dcf63e2d.tar.gz rust-99e3034bd2dc400a15063a347d322b43dcf63e2d.zip | |
fix endianess handling in eventfd::write
| -rw-r--r-- | src/tools/miri/src/shims/unix/fs.rs | 19 | ||||
| -rw-r--r-- | src/tools/miri/src/shims/unix/linux/fd/event.rs | 15 |
2 files changed, 26 insertions, 8 deletions
diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index 385fa366b20..abec782b4f0 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -11,6 +11,7 @@ use std::time::SystemTime; use log::trace; use rustc_data_structures::fx::FxHashMap; +use rustc_middle::ty::TyCtxt; use rustc_target::abi::{Align, Size}; use crate::shims::os_str::bytes_to_os_str; @@ -31,6 +32,7 @@ pub trait FileDescriptor: std::fmt::Debug + helpers::AsAny { &mut self, _communicate_allowed: bool, _bytes: &mut [u8], + _tcx: TyCtxt<'tcx>, ) -> InterpResult<'tcx, io::Result<usize>> { throw_unsup_format!("cannot read from {}", self.name()); } @@ -39,6 +41,7 @@ pub trait FileDescriptor: std::fmt::Debug + helpers::AsAny { &self, _communicate_allowed: bool, _bytes: &[u8], + _tcx: TyCtxt<'tcx>, ) -> InterpResult<'tcx, io::Result<usize>> { throw_unsup_format!("cannot write to {}", self.name()); } @@ -79,6 +82,7 @@ impl FileDescriptor for FileHandle { &mut self, communicate_allowed: bool, bytes: &mut [u8], + _tcx: TyCtxt<'tcx>, ) -> InterpResult<'tcx, io::Result<usize>> { assert!(communicate_allowed, "isolation should have prevented even opening a file"); Ok(self.file.read(bytes)) @@ -88,6 +92,7 @@ impl FileDescriptor for FileHandle { &self, communicate_allowed: bool, bytes: &[u8], + _tcx: TyCtxt<'tcx>, ) -> InterpResult<'tcx, io::Result<usize>> { assert!(communicate_allowed, "isolation should have prevented even opening a file"); Ok((&mut &self.file).write(bytes)) @@ -153,6 +158,7 @@ impl FileDescriptor for io::Stdin { &mut self, communicate_allowed: bool, bytes: &mut [u8], + _tcx: TyCtxt<'tcx>, ) -> InterpResult<'tcx, io::Result<usize>> { if !communicate_allowed { // 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 { &self, _communicate_allowed: bool, bytes: &[u8], + _tcx: TyCtxt<'tcx>, ) -> InterpResult<'tcx, io::Result<usize>> { // We allow writing to stderr even with isolation enabled. let result = Write::write(&mut { self }, bytes); @@ -220,6 +227,7 @@ impl FileDescriptor for io::Stderr { &self, _communicate_allowed: bool, bytes: &[u8], + _tcx: TyCtxt<'tcx>, ) -> InterpResult<'tcx, io::Result<usize>> { // We allow writing to stderr even with isolation enabled. // No need to flush, stderr is not buffered. @@ -252,6 +260,7 @@ impl FileDescriptor for NullOutput { &self, _communicate_allowed: bool, bytes: &[u8], + _tcx: TyCtxt<'tcx>, ) -> InterpResult<'tcx, io::Result<usize>> { // We just don't write anything, but report to the user that we did. Ok(Ok(bytes.len())) @@ -756,8 +765,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let mut bytes = vec![0; usize::try_from(count).unwrap()]; // `File::read` never returns a value larger than `count`, // so this cannot fail. - let result = - file_descriptor.read(communicate, &mut bytes)?.map(|c| i64::try_from(c).unwrap()); + let result = file_descriptor + .read(communicate, &mut bytes, *this.tcx)? + .map(|c| i64::try_from(c).unwrap()); match result { Ok(read_bytes) => { @@ -803,8 +813,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { if let Some(file_descriptor) = this.machine.file_handler.handles.get(&fd) { let bytes = this.read_bytes_ptr_strip_provenance(buf, Size::from_bytes(count))?; - let result = - file_descriptor.write(communicate, bytes)?.map(|c| i64::try_from(c).unwrap()); + let result = file_descriptor + .write(communicate, bytes, *this.tcx)? + .map(|c| i64::try_from(c).unwrap()); this.try_unwrap_io_result(result) } else { this.handle_not_found() diff --git a/src/tools/miri/src/shims/unix/linux/fd/event.rs b/src/tools/miri/src/shims/unix/linux/fd/event.rs index 1db020bb7b6..1f17ffb88c8 100644 --- a/src/tools/miri/src/shims/unix/linux/fd/event.rs +++ b/src/tools/miri/src/shims/unix/linux/fd/event.rs @@ -1,6 +1,8 @@ use crate::shims::unix::fs::FileDescriptor; use rustc_const_eval::interpret::InterpResult; +use rustc_middle::ty::TyCtxt; +use rustc_target::abi::Endian; use std::cell::Cell; use std::io; @@ -36,7 +38,7 @@ impl FileDescriptor for Event { } /// A write call adds the 8-byte integer value supplied in - /// its buffer to the counter. The maximum value that may be + /// its buffer (in native endianess) to the counter. The maximum value that may be /// stored in the counter is the largest unsigned 64-bit value /// minus 1 (i.e., 0xfffffffffffffffe). If the addition would /// cause the counter's value to exceed the maximum, then the @@ -47,17 +49,22 @@ impl FileDescriptor for Event { /// A write fails with the error EINVAL if the size of the /// supplied buffer is less than 8 bytes, or if an attempt is /// made to write the value 0xffffffffffffffff. - /// - /// FIXME: use endianness fn write<'tcx>( &self, _communicate_allowed: bool, bytes: &[u8], + tcx: TyCtxt<'tcx>, ) -> InterpResult<'tcx, io::Result<usize>> { let v1 = self.val.get(); + let bytes: [u8; 8] = bytes.try_into().unwrap(); // FIXME fail gracefully when this has the wrong size + // Convert from target endianess to host endianess. + let num = match tcx.sess.target.endian { + Endian::Little => u64::from_le_bytes(bytes), + Endian::Big => u64::from_be_bytes(bytes), + }; // FIXME handle blocking when addition results in exceeding the max u64 value // or fail with EAGAIN if the file descriptor is nonblocking. - let v2 = v1.checked_add(u64::from_be_bytes(bytes.try_into().unwrap())).unwrap(); + let v2 = v1.checked_add(num).unwrap(); self.val.set(v2); assert_eq!(8, bytes.len()); Ok(Ok(8)) |
