@@ -3,12 +3,13 @@ use std::io;
3
3
use std:: io:: { IsTerminal , Read , Seek , SeekFrom , Write } ;
4
4
use std:: path:: { Path , PathBuf } ;
5
5
use std:: time:: SystemTime ;
6
+
6
7
use rustc_abi:: Size ;
7
8
8
- use crate :: shims:: windows:: handle:: { Handle , EvalContextExt as _, PseudoHandle } ;
9
- use crate :: * ;
10
- use crate :: shims:: files:: { FileDescription , FileDescriptionRef , EvalContextExt as _} ;
9
+ use crate :: shims:: files:: { EvalContextExt as _, FileDescription , FileDescriptionRef } ;
11
10
use crate :: shims:: time:: system_time_to_duration;
11
+ use crate :: shims:: windows:: handle:: { EvalContextExt as _, Handle , PseudoHandle } ;
12
+ use crate :: * ;
12
13
13
14
#[ derive( Debug ) ]
14
15
pub struct FileHandle {
@@ -149,7 +150,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
149
150
this. assert_target_os ( "windows" , "CreateFileW" ) ;
150
151
this. check_no_isolation ( "`CreateFileW`" ) ?;
151
152
152
- let file_name = String :: from_utf16_lossy ( & this. read_wide_str ( this. read_pointer ( file_name) ?) ?) ;
153
+ let file_name =
154
+ String :: from_utf16_lossy ( & this. read_wide_str ( this. read_pointer ( file_name) ?) ?) ;
153
155
let file_name = Path :: new ( & file_name) ;
154
156
let desired_access = this. read_scalar ( desired_access) ?. to_u32 ( ) ?;
155
157
let share_mode = this. read_scalar ( share_mode) ?. to_u32 ( ) ?;
@@ -169,7 +171,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
169
171
let file_share_read = this. eval_windows_u32 ( "c" , "FILE_SHARE_READ" ) ;
170
172
let file_share_write = this. eval_windows_u32 ( "c" , "FILE_SHARE_WRITE" ) ;
171
173
172
- if share_mode & !( file_share_delete | file_share_read | file_share_write) != 0 || share_mode == 0 {
174
+ if share_mode & !( file_share_delete | file_share_read | file_share_write) != 0
175
+ || share_mode == 0
176
+ {
173
177
throw_unsup_format ! ( "CreateFileW: Unsupported share mode: {share_mode}" ) ;
174
178
}
175
179
if !this. ptr_is_null ( security_attributes) ? {
@@ -182,25 +186,37 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
182
186
let open_existing = this. eval_windows_u32 ( "c" , "OPEN_EXISTING" ) ;
183
187
let truncate_existing = this. eval_windows_u32 ( "c" , "TRUNCATE_EXISTING" ) ;
184
188
185
- if ![ create_always, create_new, open_always, open_existing, truncate_existing] . contains ( & creation_disposition) {
186
- throw_unsup_format ! ( "CreateFileW: Unsupported creation disposition: {creation_disposition}" ) ;
189
+ if ![ create_always, create_new, open_always, open_existing, truncate_existing]
190
+ . contains ( & creation_disposition)
191
+ {
192
+ throw_unsup_format ! (
193
+ "CreateFileW: Unsupported creation disposition: {creation_disposition}"
194
+ ) ;
187
195
}
188
196
189
197
let file_attribute_normal = this. eval_windows_u32 ( "c" , "FILE_ATTRIBUTE_NORMAL" ) ;
190
198
// This must be passed to allow getting directory handles. If not passed, we error on trying
191
199
// to open directories below
192
200
let file_flag_backup_semantics = this. eval_windows_u32 ( "c" , "FILE_FLAG_BACKUP_SEMANTICS" ) ;
193
- let file_flag_open_reparse_point = this. eval_windows_u32 ( "c" , "FILE_FLAG_OPEN_REPARSE_POINT" ) ;
201
+ let file_flag_open_reparse_point =
202
+ this. eval_windows_u32 ( "c" , "FILE_FLAG_OPEN_REPARSE_POINT" ) ;
194
203
195
204
let flags_and_attributes = match flags_and_attributes {
196
205
0 => file_attribute_normal,
197
206
_ => flags_and_attributes,
198
207
} ;
199
- if !( file_attribute_normal | file_flag_backup_semantics | file_flag_open_reparse_point) & flags_and_attributes != 0 {
200
- throw_unsup_format ! ( "CreateFileW: Unsupported flags_and_attributes: {flags_and_attributes}" ) ;
208
+ if !( file_attribute_normal | file_flag_backup_semantics | file_flag_open_reparse_point)
209
+ & flags_and_attributes
210
+ != 0
211
+ {
212
+ throw_unsup_format ! (
213
+ "CreateFileW: Unsupported flags_and_attributes: {flags_and_attributes}"
214
+ ) ;
201
215
}
202
216
203
- if flags_and_attributes & file_flag_open_reparse_point != 0 && creation_disposition == create_always {
217
+ if flags_and_attributes & file_flag_open_reparse_point != 0
218
+ && creation_disposition == create_always
219
+ {
204
220
throw_machine_stop ! ( TerminationInfo :: Abort ( "Invalid CreateFileW argument combination: FILE_FLAG_OPEN_REPARSE_POINT with CREATE_ALWAYS" . to_string( ) ) ) ;
205
221
}
206
222
@@ -286,7 +302,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
286
302
this. check_no_isolation ( "`GetFileInformationByHandle`" ) ?;
287
303
288
304
let file = this. read_handle ( file) ?;
289
- let file_information = this. deref_pointer_as ( file_information, this. windows_ty_layout ( "BY_HANDLE_FILE_INFORMATION" ) ) ?;
305
+ let file_information = this. deref_pointer_as (
306
+ file_information,
307
+ this. windows_ty_layout ( "BY_HANDLE_FILE_INFORMATION" ) ,
308
+ ) ?;
290
309
291
310
let fd = if let Handle :: File ( fd) = file {
292
311
fd
@@ -302,7 +321,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
302
321
Ok ( meta) => meta,
303
322
Err ( e) => {
304
323
this. set_last_error ( e) ?;
305
- return interp_ok ( this. eval_windows ( "c" , "FALSE" ) )
324
+ return interp_ok ( this. eval_windows ( "c" , "FALSE" ) ) ;
306
325
}
307
326
} ;
308
327
@@ -317,12 +336,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
317
336
this. eval_windows_u32 ( "c" , "FILE_ATTRIBUTE_DEVICE" )
318
337
} ;
319
338
320
- let created = extract_windows_epoch ( metadata. created ( ) ) ?
321
- . unwrap_or ( ( 0 , 0 ) ) ;
322
- let accessed = extract_windows_epoch ( metadata. accessed ( ) ) ?
323
- . unwrap_or ( ( 0 , 0 ) ) ;
324
- let written = extract_windows_epoch ( metadata. modified ( ) ) ?
325
- . unwrap_or ( ( 0 , 0 ) ) ;
339
+ let created = extract_windows_epoch ( metadata. created ( ) ) ?. unwrap_or ( ( 0 , 0 ) ) ;
340
+ let accessed = extract_windows_epoch ( metadata. accessed ( ) ) ?. unwrap_or ( ( 0 , 0 ) ) ;
341
+ let written = extract_windows_epoch ( metadata. modified ( ) ) ?. unwrap_or ( ( 0 , 0 ) ) ;
326
342
327
343
this. write_int_fields_named (
328
344
& [ ( "dwFileAttributes" , attributes as i128 ) ] ,
@@ -354,7 +370,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
354
370
let this = self . eval_context_mut ( ) ;
355
371
this. assert_target_os ( "windows" , "DeleteFileW" ) ;
356
372
this. check_no_isolation ( "`DeleteFileW`" ) ?;
357
- let file_name = String :: from_utf16_lossy ( & this. read_wide_str ( this. read_pointer ( file_name) ?) ?) ;
373
+ let file_name =
374
+ String :: from_utf16_lossy ( & this. read_wide_str ( this. read_pointer ( file_name) ?) ?) ;
358
375
let file_name = Path :: new ( & file_name) ;
359
376
match std:: fs:: remove_file ( file_name) {
360
377
Ok ( _) => interp_ok ( this. eval_windows ( "c" , "TRUE" ) ) ,
@@ -387,8 +404,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
387
404
let n = this. read_scalar ( n) ?. to_u32 ( ) ?;
388
405
let byte_offset = this. read_target_usize ( byte_offset) ?; // is actually a pointer
389
406
let key = this. read_pointer ( key) ?;
390
- let io_status_block = this
391
- . deref_pointer_as ( io_status_block, this. windows_ty_layout ( "IO_STATUS_BLOCK" ) ) ?;
407
+ let io_status_block =
408
+ this . deref_pointer_as ( io_status_block, this. windows_ty_layout ( "IO_STATUS_BLOCK" ) ) ?;
392
409
393
410
if event != Handle :: Null {
394
411
throw_unsup_format ! (
@@ -415,9 +432,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
415
432
}
416
433
417
434
if !this. ptr_is_null ( key) ? {
418
- throw_unsup_format ! (
419
- "`NtWriteFile` `Key` parameter is not null, which is unsupported"
420
- ) ;
435
+ throw_unsup_format ! ( "`NtWriteFile` `Key` parameter is not null, which is unsupported" ) ;
421
436
}
422
437
423
438
let written = match handle {
@@ -454,10 +469,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
454
469
if let Some ( n) = written {
455
470
let io_status_information =
456
471
this. project_field_named ( & io_status_block, "Information" ) ?;
457
- this. write_scalar (
458
- Scalar :: from_target_usize ( n. into ( ) , this) ,
459
- & io_status_information,
460
- ) ?;
472
+ this. write_scalar ( Scalar :: from_target_usize ( n. into ( ) , this) , & io_status_information) ?;
461
473
}
462
474
463
475
// Return whether this was a success. >= 0 is success.
@@ -487,8 +499,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
487
499
let n = this. read_scalar ( n) ?. to_u32 ( ) ?;
488
500
let byte_offset = this. read_target_usize ( byte_offset) ?; // is actually a pointer
489
501
let key = this. read_pointer ( key) ?;
490
- let io_status_block = this
491
- . deref_pointer_as ( io_status_block, this. windows_ty_layout ( "IO_STATUS_BLOCK" ) ) ?;
502
+ let io_status_block =
503
+ this . deref_pointer_as ( io_status_block, this. windows_ty_layout ( "IO_STATUS_BLOCK" ) ) ?;
492
504
493
505
if event != Handle :: Null {
494
506
throw_unsup_format ! (
@@ -515,17 +527,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
515
527
}
516
528
517
529
if !this. ptr_is_null ( key) ? {
518
- throw_unsup_format ! (
519
- "`NtWriteFile` `Key` parameter is not null, which is unsupported"
520
- ) ;
530
+ throw_unsup_format ! ( "`NtWriteFile` `Key` parameter is not null, which is unsupported" ) ;
521
531
}
522
532
523
533
let read = match handle {
524
534
Handle :: Pseudo ( PseudoHandle :: Stdin ) => {
525
535
// stdout/stderr
526
536
let mut buf_cont = vec ! [ 0u8 ; n as usize ] ;
527
- let res =
528
- io:: Read :: read ( & mut io:: stdin ( ) , & mut buf_cont) ;
537
+ let res = io:: Read :: read ( & mut io:: stdin ( ) , & mut buf_cont) ;
529
538
this. write_bytes_ptr ( buf, buf_cont) ?;
530
539
// We write at most `n` bytes, which is a `u32`, so we cannot have written more than that.
531
540
res. ok ( ) . map ( |n| u32:: try_from ( n) . unwrap ( ) )
@@ -549,10 +558,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
549
558
if let Some ( n) = read {
550
559
let io_status_information =
551
560
this. project_field_named ( & io_status_block, "Information" ) ?;
552
- this. write_scalar (
553
- Scalar :: from_target_usize ( n. into ( ) , this) ,
554
- & io_status_information,
555
- ) ?;
561
+ this. write_scalar ( Scalar :: from_target_usize ( n. into ( ) , this) , & io_status_information) ?;
556
562
}
557
563
558
564
// Return whether this was a success. >= 0 is success.
@@ -598,12 +604,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
598
604
599
605
match desc. seek ( this. machine . communicate ( ) , seek) ? {
600
606
Ok ( n) => {
601
- this. write_scalar (
602
- Scalar :: from_i64 ( n as i64 ) ,
603
- & this. deref_pointer ( new_fp) ?,
604
- ) ?;
607
+ this. write_scalar ( Scalar :: from_i64 ( n as i64 ) , & this. deref_pointer ( new_fp) ?) ?;
605
608
interp_ok ( this. eval_windows ( "c" , "TRUE" ) )
606
- } ,
609
+ }
607
610
Err ( e) => {
608
611
this. set_last_error ( e) ?;
609
612
interp_ok ( this. eval_windows ( "c" , "FALSE" ) )
@@ -630,7 +633,12 @@ fn extract_windows_epoch<'tcx>(
630
633
}
631
634
}
632
635
633
- fn write_filetime_field < ' tcx > ( cx : & mut MiriInterpCx < ' tcx > , val : & MPlaceTy < ' tcx > , name : & str , ( low, high) : ( u32 , u32 ) ) -> InterpResult < ' tcx > {
636
+ fn write_filetime_field < ' tcx > (
637
+ cx : & mut MiriInterpCx < ' tcx > ,
638
+ val : & MPlaceTy < ' tcx > ,
639
+ name : & str ,
640
+ ( low, high) : ( u32 , u32 ) ,
641
+ ) -> InterpResult < ' tcx > {
634
642
cx. write_int_fields_named (
635
643
& [ ( "dwLowDateTime" , low as i128 ) , ( "dwHighDateTime" , high as i128 ) ] ,
636
644
& cx. project_field_named ( val, name) ?,
0 commit comments