1
1
use std:: collections:: HashMap ;
2
- use std:: fs:: { File , OpenOptions } ;
3
- use std:: io:: { Read , Write } ;
2
+ use std:: fs:: { File , OpenOptions } ;
3
+ use std:: io:: { Read , Write } ;
4
4
5
5
use rustc:: ty:: layout:: Size ;
6
6
@@ -130,10 +130,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
130
130
131
131
let fd = this. read_scalar ( fd_op) ?. to_i32 ( ) ?;
132
132
133
- this. remove_handle_and (
134
- fd,
135
- |handle, this| this. consume_result ( handle. file . sync_all ( ) . map ( |_| 0i32 ) ) ,
136
- )
133
+ this. remove_handle_and ( fd, |handle, this| {
134
+ this. consume_result ( handle. file . sync_all ( ) . map ( |_| 0i32 ) )
135
+ } )
137
136
}
138
137
139
138
fn read (
@@ -155,22 +154,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
155
154
let count = this. read_scalar ( count_op) ?. to_usize ( & * this. tcx ) ?;
156
155
157
156
// Remove the file handle to avoid borrowing issues
158
- this. remove_handle_and (
159
- fd,
160
- |mut handle, this| {
161
- let bytes = handle
162
- . file
163
- . read ( this. memory_mut ( ) . get_mut ( buf. alloc_id ) ?. get_bytes_mut (
164
- tcx,
165
- buf,
166
- Size :: from_bytes ( count) ,
167
- ) ?)
168
- . map ( |bytes| bytes as i64 ) ;
169
- // Reinsert the file handle
170
- this. machine . file_handler . handles . insert ( fd, handle) ;
171
- this. consume_result ( bytes)
172
- } ,
173
- )
157
+ this. remove_handle_and ( fd, |mut handle, this| {
158
+ // Don't use `?` to avoid returning before reinserting the handle
159
+ let bytes = this
160
+ . memory_mut ( )
161
+ . get_mut ( buf. alloc_id ) ?
162
+ . get_bytes_mut ( tcx, buf, Size :: from_bytes ( count) )
163
+ . map ( |buffer| handle. file . read ( buffer) . map ( |bytes| bytes as i64 ) ) ;
164
+ // Reinsert the file handle
165
+ this. machine . file_handler . handles . insert ( fd, handle) ;
166
+ this. consume_result ( bytes?)
167
+ } )
174
168
}
175
169
176
170
fn write (
@@ -191,13 +185,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
191
185
let buf = this. force_ptr ( this. read_scalar ( buf_op) ?. not_undef ( ) ?) ?;
192
186
let count = this. read_scalar ( count_op) ?. to_usize ( & * this. tcx ) ?;
193
187
194
- // `to_vec` is needed to avoid borrowing issues when writing to the file.
195
- let bytes = this. memory ( ) . get ( buf. alloc_id ) ?. get_bytes ( tcx, buf, Size :: from_bytes ( count) ) ?. to_vec ( ) ;
196
-
197
188
this. remove_handle_and ( fd, |mut handle, this| {
198
- let bytes = handle. file . write ( & bytes) . map ( |bytes| bytes as i64 ) ;
189
+ let bytes = this. memory ( ) . get ( buf. alloc_id ) . and_then ( |alloc| {
190
+ alloc
191
+ . get_bytes ( tcx, buf, Size :: from_bytes ( count) )
192
+ . map ( |bytes| handle. file . write ( bytes) . map ( |bytes| bytes as i64 ) )
193
+ } ) ;
199
194
this. machine . file_handler . handles . insert ( fd, handle) ;
200
- this. consume_result ( bytes)
195
+ this. consume_result ( bytes? )
201
196
} )
202
197
}
203
198
@@ -251,7 +246,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
251
246
///
252
247
/// This function uses `T: From<i32>` instead of `i32` directly because some IO related
253
248
/// functions return different integer types (like `read`, that returns an `i64`)
254
- fn consume_result < T : From < i32 > > ( & mut self , result : std:: io:: Result < T > ) -> InterpResult < ' tcx , T > {
249
+ fn consume_result < T : From < i32 > > (
250
+ & mut self ,
251
+ result : std:: io:: Result < T > ,
252
+ ) -> InterpResult < ' tcx , T > {
255
253
match result {
256
254
Ok ( ok) => Ok ( ok) ,
257
255
Err ( e) => {
0 commit comments