From 99c6b2e604125f99bd7e66326dcf1f31a81febac Mon Sep 17 00:00:00 2001 From: Luv-Ray Date: Mon, 13 May 2024 16:17:56 +0800 Subject: [PATCH] Give `FileDescription::{read, write}` access to the `InterpCx` --- src/tools/miri/src/shims/unix/fd.rs | 37 ++++++++++++------- src/tools/miri/src/shims/unix/fs.rs | 5 +-- .../miri/src/shims/unix/linux/eventfd.rs | 5 +-- 3 files changed, 28 insertions(+), 19 deletions(-) diff --git a/src/tools/miri/src/shims/unix/fd.rs b/src/tools/miri/src/shims/unix/fd.rs index a53cd607ef0..8159960f826 100644 --- a/src/tools/miri/src/shims/unix/fd.rs +++ b/src/tools/miri/src/shims/unix/fd.rs @@ -7,7 +7,6 @@ use std::collections::BTreeMap; use std::io::{self, ErrorKind, IsTerminal, Read, SeekFrom, Write}; use std::rc::Rc; -use rustc_middle::ty::TyCtxt; use rustc_target::abi::Size; use crate::shims::unix::*; @@ -22,7 +21,7 @@ pub trait FileDescription: std::fmt::Debug + Any { &mut self, _communicate_allowed: bool, _bytes: &mut [u8], - _tcx: TyCtxt<'tcx>, + _ecx: &mut MiriInterpCx<'_, 'tcx>, ) -> InterpResult<'tcx, io::Result> { throw_unsup_format!("cannot read from {}", self.name()); } @@ -32,7 +31,7 @@ pub trait FileDescription: std::fmt::Debug + Any { &mut self, _communicate_allowed: bool, _bytes: &[u8], - _tcx: TyCtxt<'tcx>, + _ecx: &mut MiriInterpCx<'_, 'tcx>, ) -> InterpResult<'tcx, io::Result> { throw_unsup_format!("cannot write to {}", self.name()); } @@ -82,7 +81,7 @@ impl FileDescription for io::Stdin { &mut self, communicate_allowed: bool, bytes: &mut [u8], - _tcx: TyCtxt<'tcx>, + _ecx: &mut MiriInterpCx<'_, 'tcx>, ) -> InterpResult<'tcx, io::Result> { if !communicate_allowed { // We want isolation mode to be deterministic, so we have to disallow all reads, even stdin. @@ -105,7 +104,7 @@ impl FileDescription for io::Stdout { &mut self, _communicate_allowed: bool, bytes: &[u8], - _tcx: TyCtxt<'tcx>, + _ecx: &mut MiriInterpCx<'_, 'tcx>, ) -> InterpResult<'tcx, io::Result> { // We allow writing to stderr even with isolation enabled. let result = Write::write(self, bytes); @@ -133,7 +132,7 @@ impl FileDescription for io::Stderr { &mut self, _communicate_allowed: bool, bytes: &[u8], - _tcx: TyCtxt<'tcx>, + _ecx: &mut MiriInterpCx<'_, 'tcx>, ) -> InterpResult<'tcx, io::Result> { // We allow writing to stderr even with isolation enabled. // No need to flush, stderr is not buffered. @@ -158,7 +157,7 @@ impl FileDescription for NullOutput { &mut self, _communicate_allowed: bool, bytes: &[u8], - _tcx: TyCtxt<'tcx>, + _ecx: &mut MiriInterpCx<'_, 'tcx>, ) -> InterpResult<'tcx, io::Result> { // We just don't write anything, but report to the user that we did. Ok(Ok(bytes.len())) @@ -173,6 +172,14 @@ impl FileDescriptor { FileDescriptor(Rc::new(RefCell::new(Box::new(fd)))) } + pub fn borrow(&self) -> Ref<'_, dyn FileDescription> { + Ref::map(self.0.borrow(), |fd| fd.as_ref()) + } + + pub fn borrow_mut(&self) -> RefMut<'_, dyn FileDescription> { + RefMut::map(self.0.borrow_mut(), |fd| fd.as_mut()) + } + pub fn close<'ctx>(self, communicate_allowed: bool) -> InterpResult<'ctx, io::Result<()>> { // Destroy this `Rc` using `into_inner` so we can call `close` instead of // implicitly running the destructor of the file description. @@ -242,12 +249,12 @@ impl FdTable { pub fn get(&self, fd: i32) -> Option> { let fd = self.fds.get(&fd)?; - Some(Ref::map(fd.0.borrow(), |fd| fd.as_ref())) + Some(fd.borrow()) } pub fn get_mut(&self, fd: i32) -> Option> { let fd = self.fds.get(&fd)?; - Some(RefMut::map(fd.0.borrow_mut(), |fd| fd.as_mut())) + Some(fd.borrow_mut()) } pub fn dup(&self, fd: i32) -> Option { @@ -370,7 +377,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { .min(u64::try_from(isize::MAX).unwrap()); let communicate = this.machine.communicate(); - let Some(mut file_descriptor) = this.machine.fds.get_mut(fd) else { + // We temporarily dup the FD to be able to retain mutable access to `this`. + let Some(file_descriptor) = this.machine.fds.dup(fd) else { trace!("read: FD not found"); return this.fd_not_found(); }; @@ -383,7 +391,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // `File::read` never returns a value larger than `count`, // so this cannot fail. let result = file_descriptor - .read(communicate, &mut bytes, *this.tcx)? + .borrow_mut() + .read(communicate, &mut bytes, this)? .map(|c| i64::try_from(c).unwrap()); drop(file_descriptor); @@ -421,12 +430,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let communicate = this.machine.communicate(); let bytes = this.read_bytes_ptr_strip_provenance(buf, Size::from_bytes(count))?.to_owned(); - let Some(mut file_descriptor) = this.machine.fds.get_mut(fd) else { + // We temporarily dup the FD to be able to retain mutable access to `this`. + let Some(file_descriptor) = this.machine.fds.dup(fd) else { return this.fd_not_found(); }; let result = file_descriptor - .write(communicate, &bytes, *this.tcx)? + .borrow_mut() + .write(communicate, &bytes, this)? .map(|c| i64::try_from(c).unwrap()); drop(file_descriptor); diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index eb241556a56..82bc49536b0 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -9,7 +9,6 @@ use std::path::{Path, PathBuf}; use std::time::SystemTime; use rustc_data_structures::fx::FxHashMap; -use rustc_middle::ty::TyCtxt; use rustc_target::abi::Size; use crate::shims::os_str::bytes_to_os_str; @@ -34,7 +33,7 @@ impl FileDescription for FileHandle { &mut self, communicate_allowed: bool, bytes: &mut [u8], - _tcx: TyCtxt<'tcx>, + _ecx: &mut MiriInterpCx<'_, 'tcx>, ) -> InterpResult<'tcx, io::Result> { assert!(communicate_allowed, "isolation should have prevented even opening a file"); Ok(self.file.read(bytes)) @@ -44,7 +43,7 @@ impl FileDescription for FileHandle { &mut self, communicate_allowed: bool, bytes: &[u8], - _tcx: TyCtxt<'tcx>, + _ecx: &mut MiriInterpCx<'_, 'tcx>, ) -> InterpResult<'tcx, io::Result> { assert!(communicate_allowed, "isolation should have prevented even opening a file"); Ok(self.file.write(bytes)) diff --git a/src/tools/miri/src/shims/unix/linux/eventfd.rs b/src/tools/miri/src/shims/unix/linux/eventfd.rs index a865f2efff9..f31c2bb84ae 100644 --- a/src/tools/miri/src/shims/unix/linux/eventfd.rs +++ b/src/tools/miri/src/shims/unix/linux/eventfd.rs @@ -2,7 +2,6 @@ //! Currently just a stub. use std::io; -use rustc_middle::ty::TyCtxt; use rustc_target::abi::Endian; use crate::shims::unix::*; @@ -52,11 +51,11 @@ impl FileDescription for Event { &mut self, _communicate_allowed: bool, bytes: &[u8], - tcx: TyCtxt<'tcx>, + ecx: &mut MiriInterpCx<'_, 'tcx>, ) -> InterpResult<'tcx, io::Result> { let bytes: [u8; 8] = bytes.try_into().unwrap(); // FIXME fail gracefully when this has the wrong size // Convert from target endianness to host endianness. - let num = match tcx.sess.target.endian { + let num = match ecx.tcx.sess.target.endian { Endian::Little => u64::from_le_bytes(bytes), Endian::Big => u64::from_be_bytes(bytes), };