Use &[u8] instead of Vec<u8> and improve docs

This commit is contained in:
tiif 2024-09-17 16:16:38 +08:00 committed by Ralf Jung
parent f392648c15
commit 503b6af065
3 changed files with 25 additions and 13 deletions

View File

@ -26,7 +26,9 @@ pub trait FileDescription: std::fmt::Debug + Any {
fn name(&self) -> &'static str; fn name(&self) -> &'static str;
/// Reads as much as possible into the given buffer, and returns the number of bytes read. /// Reads as much as possible into the given buffer, and returns the number of bytes read.
/// `ptr` is the pointer to user supplied read buffer. /// `ptr` is the pointer to the user supplied read buffer.
/// `len` indicates how many bytes the user requested.
/// `dest` is where the return value should be stored.
fn read<'tcx>( fn read<'tcx>(
&self, &self,
_self_ref: &FileDescriptionRef, _self_ref: &FileDescriptionRef,
@ -40,6 +42,8 @@ pub trait FileDescription: std::fmt::Debug + Any {
} }
/// Writes as much as possible from the given buffer, and returns the number of bytes written. /// Writes as much as possible from the given buffer, and returns the number of bytes written.
/// `bytes` is the buffer of bytes supplied by the caller to be written.
/// `dest` is where the return value should be stored.
fn write<'tcx>( fn write<'tcx>(
&self, &self,
_self_ref: &FileDescriptionRef, _self_ref: &FileDescriptionRef,
@ -53,6 +57,9 @@ pub trait FileDescription: std::fmt::Debug + Any {
/// Reads as much as possible into the given buffer from a given offset, /// Reads as much as possible into the given buffer from a given offset,
/// and returns the number of bytes read. /// and returns the number of bytes read.
/// `ptr` is the pointer to the user supplied read buffer.
/// `len` indicates how many bytes the user requested.
/// `dest` is where the return value should be stored.
fn pread<'tcx>( fn pread<'tcx>(
&self, &self,
_communicate_allowed: bool, _communicate_allowed: bool,
@ -67,6 +74,8 @@ pub trait FileDescription: std::fmt::Debug + Any {
/// Writes as much as possible from the given buffer starting at a given offset, /// Writes as much as possible from the given buffer starting at a given offset,
/// and returns the number of bytes written. /// and returns the number of bytes written.
/// `bytes` is the buffer of bytes supplied by the caller to be written.
/// `dest` is where the return value should be stored.
fn pwrite<'tcx>( fn pwrite<'tcx>(
&self, &self,
_communicate_allowed: bool, _communicate_allowed: bool,
@ -143,7 +152,7 @@ impl FileDescription for io::Stdin {
helpers::isolation_abort_error("`read` from stdin")?; helpers::isolation_abort_error("`read` from stdin")?;
} }
let result = Read::read(&mut { self }, &mut bytes); let result = Read::read(&mut { self }, &mut bytes);
ecx.return_read_bytes_and_count(ptr, bytes, result, dest) ecx.return_read_bytes_and_count(ptr, &bytes, result, dest)
} }
fn is_tty(&self, communicate_allowed: bool) -> bool { fn is_tty(&self, communicate_allowed: bool) -> bool {
@ -641,12 +650,15 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
Ok(()) Ok(())
} }
/// This function either writes to the user supplied buffer and to dest place, or sets the /// Helper to implement `FileDescription::read`:
/// last libc error and writes -1 to dest. /// `result` should be the return value of some underlying `read` call that used `bytes` as its output buffer.
/// The length of `bytes` must not exceed either the host's or the target's `isize`.
/// If `Result` indicates success, `bytes` is written to `buf` and the size is written to `dest`.
/// Otherwise, `-1` is written to `dest` and the last libc error is set appropriately.
fn return_read_bytes_and_count( fn return_read_bytes_and_count(
&mut self, &mut self,
buf: Pointer, buf: Pointer,
bytes: Vec<u8>, bytes: &[u8],
result: io::Result<usize>, result: io::Result<usize>,
dest: &MPlaceTy<'tcx>, dest: &MPlaceTy<'tcx>,
) -> InterpResult<'tcx> { ) -> InterpResult<'tcx> {
@ -657,7 +669,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Crucially, if fewer than `bytes.len()` bytes were read, only write // Crucially, if fewer than `bytes.len()` bytes were read, only write
// that much into the output buffer! // that much into the output buffer!
this.write_bytes_ptr(buf, bytes[..read_bytes].iter().copied())?; this.write_bytes_ptr(buf, bytes[..read_bytes].iter().copied())?;
// The actual read size is always lesser than `count` so this cannot fail. // The actual read size is always less than what got originally requested so this cannot fail.
this.write_int(u64::try_from(read_bytes).unwrap(), dest)?; this.write_int(u64::try_from(read_bytes).unwrap(), dest)?;
return Ok(()); return Ok(());
} }
@ -669,7 +681,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
} }
} }
/// This function writes the number of written bytes to dest place, or sets the /// This function writes the number of written bytes (given in `result`) to `dest`, or sets the
/// last libc error and writes -1 to dest. /// last libc error and writes -1 to dest.
fn return_written_byte_count_or_error( fn return_written_byte_count_or_error(
&mut self, &mut self,

View File

@ -42,7 +42,7 @@ impl FileDescription for FileHandle {
assert!(communicate_allowed, "isolation should have prevented even opening a file"); assert!(communicate_allowed, "isolation should have prevented even opening a file");
let mut bytes = vec![0; usize::try_from(len).unwrap()]; let mut bytes = vec![0; usize::try_from(len).unwrap()];
let result = (&mut &self.file).read(&mut bytes); let result = (&mut &self.file).read(&mut bytes);
ecx.return_read_bytes_and_count(ptr, bytes.to_vec(), result, dest) ecx.return_read_bytes_and_count(ptr, &bytes, result, dest)
} }
fn write<'tcx>( fn write<'tcx>(
@ -83,7 +83,7 @@ impl FileDescription for FileHandle {
res res
}; };
let result = f(); let result = f();
ecx.return_read_bytes_and_count(ptr, bytes.to_vec(), result, dest) ecx.return_read_bytes_and_count(ptr, &bytes, result, dest)
} }
fn pwrite<'tcx>( fn pwrite<'tcx>(

View File

@ -137,7 +137,7 @@ impl FileDescription for AnonSocket {
// Always succeed on read size 0. // Always succeed on read size 0.
if request_byte_size == 0 { if request_byte_size == 0 {
let result = Ok(0); let result = Ok(0);
return ecx.return_read_bytes_and_count(ptr, bytes.to_vec(), result, dest); return ecx.return_read_bytes_and_count(ptr, &bytes, result, dest);
} }
let Some(readbuf) = &self.readbuf else { let Some(readbuf) = &self.readbuf else {
@ -151,7 +151,7 @@ impl FileDescription for AnonSocket {
// Socketpair with no peer and empty buffer. // Socketpair with no peer and empty buffer.
// 0 bytes successfully read indicates end-of-file. // 0 bytes successfully read indicates end-of-file.
let result = Ok(0); let result = Ok(0);
return ecx.return_read_bytes_and_count(ptr, bytes.to_vec(), result, dest); return ecx.return_read_bytes_and_count(ptr, &bytes, result, dest);
} else { } else {
if self.is_nonblock { if self.is_nonblock {
// Non-blocking socketpair with writer and empty buffer. // Non-blocking socketpair with writer and empty buffer.
@ -160,7 +160,7 @@ impl FileDescription for AnonSocket {
// POSIX.1-2001 allows either error to be returned for this case. // POSIX.1-2001 allows either error to be returned for this case.
// Since there is no ErrorKind for EAGAIN, WouldBlock is used. // Since there is no ErrorKind for EAGAIN, WouldBlock is used.
let result = Err(Error::from(ErrorKind::WouldBlock)); let result = Err(Error::from(ErrorKind::WouldBlock));
return ecx.return_read_bytes_and_count(ptr, bytes.to_vec(), result, dest); return ecx.return_read_bytes_and_count(ptr, &bytes, result, dest);
} else { } else {
// Blocking socketpair with writer and empty buffer. // Blocking socketpair with writer and empty buffer.
// FIXME: blocking is currently not supported // FIXME: blocking is currently not supported
@ -193,7 +193,7 @@ impl FileDescription for AnonSocket {
} }
let result = Ok(actual_read_size); let result = Ok(actual_read_size);
ecx.return_read_bytes_and_count(ptr, bytes.to_vec(), result, dest) ecx.return_read_bytes_and_count(ptr, &bytes, result, dest)
} }
fn write<'tcx>( fn write<'tcx>(