use std::fs::{remove_file, File, OpenOptions};
use std::io::{Read, Write};
-use rustc::ty::layout::Size;
+use rustc::ty::layout::{Size, Align};
use crate::stacked_borrows::Tag;
use crate::*;
this.check_no_isolation("read")?;
- let ptr_size = this.pointer_size().bits();
-
- // We cap the number of read bytes to the largest value that we are able to fit in both the
- // host's and target's `isize`.
+ let fd = this.read_scalar(fd_op)?.to_i32()?;
+ let buf = this.read_scalar(buf_op)?.not_undef()?;
let count = this
.read_scalar(count_op)?
- .to_machine_usize(&*this.tcx)?
- .min((1 << (ptr_size - 1)) - 1) // max value of target `isize`
- .min(isize::max_value() as u64);
+ .to_machine_usize(&*this.tcx)?;
- let fd = this.read_scalar(fd_op)?.to_i32()?;
- let buf = this.read_scalar(buf_op)?.not_undef()?;
+ // Check that the *entire* buffer is actually valid memory.
+ this.memory.check_ptr_access(buf, Size::from_bytes(count), Align::from_bytes(1).unwrap())?;
+
+ // We cap the number of read bytes to the largest value that we are able to fit in both the
+ // host's and target's `isize`. This saves us from having to handle overflows later.
+ let count = count
+ .min(this.isize_max() as u64)
+ .min(isize::max_value() as u64);
if let Some(handle) = this.machine.file_handler.handles.get_mut(&fd) {
// This can never fail because `count` was capped to be smaller than
this.check_no_isolation("write")?;
- let ptr_size = this.pointer_size().bits();
-
- // We cap the number of read bytes to the largest value that we are able to fit in both the
- // host's and target's `isize`.
+ let fd = this.read_scalar(fd_op)?.to_i32()?;
+ let buf = this.read_scalar(buf_op)?.not_undef()?;
let count = this
.read_scalar(count_op)?
- .to_machine_usize(&*this.tcx)?
- .min((1 << (ptr_size - 1)) - 1) // max value of target `isize`
- .min(isize::max_value() as u64);
+ .to_machine_usize(&*this.tcx)?;
- let fd = this.read_scalar(fd_op)?.to_i32()?;
- let buf = this.read_scalar(buf_op)?.not_undef()?;
+ // Check that the *entire* buffer is actually valid memory.
+ this.memory.check_ptr_access(buf, Size::from_bytes(count), Align::from_bytes(1).unwrap())?;
+
+ // We cap the number of written bytes to the largest value that we are able to fit in both the
+ // host's and target's `isize`. This saves us from having to handle overflows later.
+ let count = count
+ .min(this.isize_max() as u64)
+ .min(isize::max_value() as u64);
if let Some(handle) = this.machine.file_handler.handles.get_mut(&fd) {
let bytes = this.memory.read_bytes(buf, Size::from_bytes(count))?;