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,18 @@ 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 ) . and_then ( |alloc|
162
+ alloc. get_bytes_mut ( tcx, buf, Size :: from_bytes ( count) )
163
+ . map ( |buffer| handle. file . read ( buffer) . map ( |bytes| bytes as i64 ) )
164
+ ) ;
165
+ // Reinsert the file handle
166
+ this. machine . file_handler . handles . insert ( fd, handle) ;
167
+ this. consume_result ( bytes?)
168
+ } )
174
169
}
175
170
176
171
fn write (
@@ -191,13 +186,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
191
186
let buf = this. force_ptr ( this. read_scalar ( buf_op) ?. not_undef ( ) ?) ?;
192
187
let count = this. read_scalar ( count_op) ?. to_usize ( & * this. tcx ) ?;
193
188
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
189
this. remove_handle_and ( fd, |mut handle, this| {
198
- let bytes = handle. file . write ( & bytes) . map ( |bytes| bytes as i64 ) ;
190
+ let bytes = this. memory ( ) . get ( buf. alloc_id ) . and_then ( |alloc| {
191
+ alloc
192
+ . get_bytes ( tcx, buf, Size :: from_bytes ( count) )
193
+ . map ( |bytes| handle. file . write ( bytes) . map ( |bytes| bytes as i64 ) )
194
+ } ) ;
199
195
this. machine . file_handler . handles . insert ( fd, handle) ;
200
- this. consume_result ( bytes)
196
+ this. consume_result ( bytes? )
201
197
} )
202
198
}
203
199
@@ -251,7 +247,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
251
247
///
252
248
/// This function uses `T: From<i32>` instead of `i32` directly because some IO related
253
249
/// 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 > {
250
+ fn consume_result < T : From < i32 > > (
251
+ & mut self ,
252
+ result : std:: io:: Result < T > ,
253
+ ) -> InterpResult < ' tcx , T > {
255
254
match result {
256
255
Ok ( ok) => Ok ( ok) ,
257
256
Err ( e) => {
0 commit comments