From 5345636f37a2934ea4c183baa2069fa50c6793cc Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 17 Nov 2019 09:30:32 +0100 Subject: [PATCH] use new isize_max method in FS accesses; also check full buffers for validity --- src/shims/fs.rs | 42 +++++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/src/shims/fs.rs b/src/shims/fs.rs index 79e57cf2c8f..9291f3a6e3b 100644 --- a/src/shims/fs.rs +++ b/src/shims/fs.rs @@ -3,7 +3,7 @@ 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::*; @@ -166,18 +166,20 @@ fn read( 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 @@ -219,18 +221,20 @@ fn write( 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))?; -- 2.44.0