@@ -2,6 +2,8 @@ use std::collections::HashMap;
2
2
use std:: fs:: File ;
3
3
use std:: io:: Read ;
4
4
5
+ use rustc:: ty:: layout:: Size ;
6
+
5
7
use crate :: stacked_borrows:: Tag ;
6
8
use crate :: * ;
7
9
@@ -53,7 +55,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
53
55
let fd = File :: open ( & path) . map ( |file| {
54
56
let mut fh = & mut this. machine . file_handler ;
55
57
fh. low += 1 ;
56
- fh. handles . insert ( fh. low , FileHandle { file, flag} ) ;
58
+ fh. handles . insert ( fh. low , FileHandle { file, flag } ) ;
57
59
fh. low
58
60
} ) ;
59
61
@@ -81,7 +83,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
81
83
let flag = this. read_scalar ( arg_op. unwrap ( ) ) ?. to_i32 ( ) ?;
82
84
// The only usage of this in stdlib at the moment is to enable the `FD_CLOEXEC` flag.
83
85
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
+ {
85
89
if flag ^ * old_flag == fd_cloexec {
86
90
* old_flag = flag;
87
91
} else {
@@ -136,23 +140,23 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
136
140
let buf = this. force_ptr ( this. read_scalar ( buf_op) ?. not_undef ( ) ?) ?;
137
141
let count = this. read_scalar ( count_op) ?. to_usize ( & * this. tcx ) ?;
138
142
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 )
143
156
} else {
144
157
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 )
154
159
}
155
- Ok ( read_bytes)
156
160
}
157
161
158
162
fn consume_result < T > ( & mut self , result : std:: io:: Result < T > , t : T ) -> InterpResult < ' tcx , T > {
0 commit comments