@@ -273,6 +273,32 @@ impl FdTable {
273
273
274
274
impl < ' tcx > EvalContextExt < ' tcx > for crate :: MiriInterpCx < ' tcx > { }
275
275
pub trait EvalContextExt < ' tcx > : crate :: MiriInterpCxExt < ' tcx > {
276
+ fn dup ( & mut self , old_fd : i32 ) -> InterpResult < ' tcx , i32 > {
277
+ let this = self . eval_context_mut ( ) ;
278
+
279
+ let Some ( dup_fd) = this. machine . fds . dup ( old_fd) else {
280
+ return this. fd_not_found ( ) ;
281
+ } ;
282
+ Ok ( this. machine . fds . insert_fd_with_min_fd ( dup_fd, 0 ) )
283
+ }
284
+
285
+ fn dup2 ( & mut self , old_fd : i32 , new_fd : i32 ) -> InterpResult < ' tcx , i32 > {
286
+ let this = self . eval_context_mut ( ) ;
287
+
288
+ let Some ( dup_fd) = this. machine . fds . dup ( old_fd) else {
289
+ return this. fd_not_found ( ) ;
290
+ } ;
291
+ if new_fd != old_fd {
292
+ // Close new_fd if it is previously opened.
293
+ // If old_fd and new_fd point to the same description, then `dup_fd` ensures we keep the underlying file description alive.
294
+ if let Some ( file_descriptor) = this. machine . fds . fds . insert ( new_fd, dup_fd) {
295
+ // Ignore close error (not interpreter's) according to dup2() doc.
296
+ file_descriptor. close ( this. machine . communicate ( ) ) ?. ok ( ) ;
297
+ }
298
+ }
299
+ Ok ( new_fd)
300
+ }
301
+
276
302
fn fcntl ( & mut self , args : & [ OpTy < ' tcx > ] ) -> InterpResult < ' tcx , i32 > {
277
303
let this = self . eval_context_mut ( ) ;
278
304
@@ -334,14 +360,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
334
360
335
361
let fd = this. read_scalar ( fd_op) ?. to_i32 ( ) ?;
336
362
337
- Ok ( Scalar :: from_i32 ( if let Some ( file_descriptor) = this. machine . fds . remove ( fd) {
338
- let result = file_descriptor. close ( this. machine . communicate ( ) ) ?;
339
- // return `0` if close is successful
340
- let result = result. map ( |( ) | 0i32 ) ;
341
- this. try_unwrap_io_result ( result) ?
342
- } else {
343
- this. fd_not_found ( ) ?
344
- } ) )
363
+ let Some ( file_descriptor) = this. machine . fds . remove ( fd) else {
364
+ return Ok ( Scalar :: from_i32 ( this. fd_not_found ( ) ?) ) ;
365
+ } ;
366
+ let result = file_descriptor. close ( this. machine . communicate ( ) ) ?;
367
+ // return `0` if close is successful
368
+ let result = result. map ( |( ) | 0i32 ) ;
369
+ Ok ( Scalar :: from_i32 ( this. try_unwrap_io_result ( result) ?) )
345
370
}
346
371
347
372
/// Function used when a file descriptor does not exist. It returns `Ok(-1)`and sets
0 commit comments