@@ -2,6 +2,8 @@ use std::collections::HashMap;
22use std:: fs:: File ;
33use std:: io:: Read ;
44
5+ use rustc:: ty:: layout:: Size ;
6+
57use crate :: stacked_borrows:: Tag ;
68use crate :: * ;
79
@@ -53,7 +55,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
5355 let fd = File :: open ( & path) . map ( |file| {
5456 let mut fh = & mut this. machine . file_handler ;
5557 fh. low += 1 ;
56- fh. handles . insert ( fh. low , FileHandle { file, flag} ) ;
58+ fh. handles . insert ( fh. low , FileHandle { file, flag } ) ;
5759 fh. low
5860 } ) ;
5961
@@ -81,7 +83,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
8183 let flag = this. read_scalar ( arg_op. unwrap ( ) ) ?. to_i32 ( ) ?;
8284 // The only usage of this in stdlib at the moment is to enable the `FD_CLOEXEC` flag.
8385 let fd_cloexec = this. eval_libc_i32 ( "FD_CLOEXEC" ) ?;
84- if let Some ( FileHandle { flag : old_flag, .. } ) = this. machine . file_handler . handles . get_mut ( & fd) {
86+ if let Some ( FileHandle { flag : old_flag, .. } ) =
87+ this. machine . file_handler . handles . get_mut ( & fd)
88+ {
8589 if flag ^ * old_flag == fd_cloexec {
8690 * old_flag = flag;
8791 } else {
@@ -136,23 +140,23 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
136140 let buf = this. force_ptr ( this. read_scalar ( buf_op) ?. not_undef ( ) ?) ?;
137141 let count = this. read_scalar ( count_op) ?. to_usize ( & * this. tcx ) ?;
138142
139- let mut bytes = vec ! [ 0 ; count as usize ] ;
140-
141- let read_result = if let Some ( FileHandle { file, ..} ) = this. machine . file_handler . handles . get_mut ( & fd) {
142- file. read ( & mut bytes) . map ( |bytes| bytes as i64 )
143+ // Remove the file handle to avoid borrowing issues
144+ if let Some ( mut handle) = this. machine . file_handler . handles . remove ( & fd) {
145+ let bytes = handle
146+ . file
147+ . read ( this. memory_mut ( ) . get_mut ( buf. alloc_id ) ?. get_bytes_mut (
148+ tcx,
149+ buf,
150+ Size :: from_bytes ( count) ,
151+ ) ?)
152+ . map ( |bytes| bytes as i64 ) ;
153+ // Reinsert the file handle
154+ this. machine . file_handler . handles . insert ( fd, handle) ;
155+ this. consume_result :: < i64 > ( bytes, -1 )
143156 } else {
144157 this. machine . last_error = this. eval_libc_i32 ( "EBADF" ) ? as u32 ;
145- return Ok ( -1 ) ;
146- } ;
147-
148- let read_bytes = this. consume_result :: < i64 > ( read_result, -1 ) ?;
149- if read_bytes != -1 {
150- bytes. truncate ( read_bytes as usize ) ;
151- this. memory_mut ( )
152- . get_mut ( buf. alloc_id ) ?
153- . write_bytes ( tcx, buf, & bytes) ?;
158+ Ok ( -1 )
154159 }
155- Ok ( read_bytes)
156160 }
157161
158162 fn consume_result < T > ( & mut self , result : std:: io:: Result < T > , t : T ) -> InterpResult < ' tcx , T > {
0 commit comments