@@ -3,7 +3,7 @@ use std::convert::TryFrom;
33use std:: fs:: { remove_file, File , OpenOptions } ;
44use std:: io:: { Read , Write } ;
55
6- use rustc:: ty:: layout:: Size ;
6+ use rustc:: ty:: layout:: { Size , Align } ;
77
88use crate :: stacked_borrows:: Tag ;
99use crate :: * ;
@@ -166,18 +166,20 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
166166
167167 this. check_no_isolation ( "read" ) ?;
168168
169- let ptr_size = this. pointer_size ( ) . bits ( ) ;
170-
171- // We cap the number of read bytes to the largest value that we are able to fit in both the
172- // host's and target's `isize`.
169+ let fd = this. read_scalar ( fd_op) ?. to_i32 ( ) ?;
170+ let buf = this. read_scalar ( buf_op) ?. not_undef ( ) ?;
173171 let count = this
174172 . read_scalar ( count_op) ?
175- . to_machine_usize ( & * this. tcx ) ?
176- . min ( ( 1 << ( ptr_size - 1 ) ) - 1 ) // max value of target `isize`
177- . min ( isize:: max_value ( ) as u64 ) ;
173+ . to_machine_usize ( & * this. tcx ) ?;
178174
179- let fd = this. read_scalar ( fd_op) ?. to_i32 ( ) ?;
180- let buf = this. read_scalar ( buf_op) ?. not_undef ( ) ?;
175+ // Check that the *entire* buffer is actually valid memory.
176+ this. memory . check_ptr_access ( buf, Size :: from_bytes ( count) , Align :: from_bytes ( 1 ) . unwrap ( ) ) ?;
177+
178+ // We cap the number of read bytes to the largest value that we are able to fit in both the
179+ // host's and target's `isize`. This saves us from having to handle overflows later.
180+ let count = count
181+ . min ( this. isize_max ( ) as u64 )
182+ . min ( isize:: max_value ( ) as u64 ) ;
181183
182184 if let Some ( handle) = this. machine . file_handler . handles . get_mut ( & fd) {
183185 // This can never fail because `count` was capped to be smaller than
@@ -219,18 +221,20 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
219221
220222 this. check_no_isolation ( "write" ) ?;
221223
222- let ptr_size = this. pointer_size ( ) . bits ( ) ;
223-
224- // We cap the number of read bytes to the largest value that we are able to fit in both the
225- // host's and target's `isize`.
224+ let fd = this. read_scalar ( fd_op) ?. to_i32 ( ) ?;
225+ let buf = this. read_scalar ( buf_op) ?. not_undef ( ) ?;
226226 let count = this
227227 . read_scalar ( count_op) ?
228- . to_machine_usize ( & * this. tcx ) ?
229- . min ( ( 1 << ( ptr_size - 1 ) ) - 1 ) // max value of target `isize`
230- . min ( isize:: max_value ( ) as u64 ) ;
228+ . to_machine_usize ( & * this. tcx ) ?;
231229
232- let fd = this. read_scalar ( fd_op) ?. to_i32 ( ) ?;
233- let buf = this. read_scalar ( buf_op) ?. not_undef ( ) ?;
230+ // Check that the *entire* buffer is actually valid memory.
231+ this. memory . check_ptr_access ( buf, Size :: from_bytes ( count) , Align :: from_bytes ( 1 ) . unwrap ( ) ) ?;
232+
233+ // We cap the number of written bytes to the largest value that we are able to fit in both the
234+ // host's and target's `isize`. This saves us from having to handle overflows later.
235+ let count = count
236+ . min ( this. isize_max ( ) as u64 )
237+ . min ( isize:: max_value ( ) as u64 ) ;
234238
235239 if let Some ( handle) = this. machine . file_handler . handles . get_mut ( & fd) {
236240 let bytes = this. memory . read_bytes ( buf, Size :: from_bytes ( count) ) ?;
0 commit comments