@@ -48,11 +48,85 @@ impl<'tcx> FileDescriptor<'tcx> for FileHandle {
4848 }
4949}
5050
51- #[ derive( Debug , Default ) ]
51+ impl < ' tcx > FileDescriptor < ' tcx > for io:: Stdin {
52+ fn as_file_handle ( & self ) -> InterpResult < ' tcx , & FileHandle > {
53+ throw_unsup_format ! ( "stdin cannot be used as FileHandle" ) ;
54+ }
55+
56+ fn read ( & mut self , bytes : & mut [ u8 ] ) -> InterpResult < ' tcx , io:: Result < usize > > {
57+ Ok ( Read :: read ( self , bytes) )
58+ }
59+
60+ fn write ( & mut self , _bytes : & [ u8 ] ) -> InterpResult < ' tcx , io:: Result < usize > > {
61+ throw_unsup_format ! ( "cannot write to stdin" ) ;
62+ }
63+
64+ fn seek ( & mut self , _offset : SeekFrom ) -> InterpResult < ' tcx , io:: Result < u64 > > {
65+ throw_unsup_format ! ( "cannot seek on stdin" ) ;
66+ }
67+ }
68+
69+ impl < ' tcx > FileDescriptor < ' tcx > for io:: Stdout {
70+ fn as_file_handle ( & self ) -> InterpResult < ' tcx , & FileHandle > {
71+ throw_unsup_format ! ( "stdout cannot be used as FileHandle" ) ;
72+ }
73+
74+ fn read ( & mut self , _bytes : & mut [ u8 ] ) -> InterpResult < ' tcx , io:: Result < usize > > {
75+ throw_unsup_format ! ( "cannot read from stdout" ) ;
76+ }
77+
78+ fn write ( & mut self , bytes : & [ u8 ] ) -> InterpResult < ' tcx , io:: Result < usize > > {
79+ let result = Write :: write ( self , bytes) ;
80+ // Stdout is buffered, flush to make sure it appears on the
81+ // screen. This is the write() syscall of the interpreted
82+ // program, we want it to correspond to a write() syscall on
83+ // the host -- there is no good in adding extra buffering
84+ // here.
85+ io:: stdout ( ) . flush ( ) . unwrap ( ) ;
86+
87+ Ok ( result)
88+ }
89+
90+ fn seek ( & mut self , _offset : SeekFrom ) -> InterpResult < ' tcx , io:: Result < u64 > > {
91+ throw_unsup_format ! ( "cannot seek on stdout" ) ;
92+ }
93+ }
94+
95+ impl < ' tcx > FileDescriptor < ' tcx > for io:: Stderr {
96+ fn as_file_handle ( & self ) -> InterpResult < ' tcx , & FileHandle > {
97+ throw_unsup_format ! ( "stdout cannot be used as FileHandle" ) ;
98+ }
99+
100+ fn read ( & mut self , _bytes : & mut [ u8 ] ) -> InterpResult < ' tcx , io:: Result < usize > > {
101+ throw_unsup_format ! ( "cannot read from stderr" ) ;
102+ }
103+
104+ fn write ( & mut self , bytes : & [ u8 ] ) -> InterpResult < ' tcx , io:: Result < usize > > {
105+ Ok ( Write :: write ( self , bytes) )
106+ }
107+
108+ fn seek ( & mut self , _offset : SeekFrom ) -> InterpResult < ' tcx , io:: Result < u64 > > {
109+ throw_unsup_format ! ( "cannot seek on stderr" ) ;
110+ }
111+ }
112+
113+ #[ derive( Debug ) ]
52114pub struct FileHandler < ' tcx > {
53115 handles : BTreeMap < i32 , Box < dyn FileDescriptor < ' tcx > > > ,
54116}
55117
118+ impl < ' tcx > Default for FileHandler < ' tcx > {
119+ fn default ( ) -> Self {
120+ let mut handles = BTreeMap :: new ( ) ;
121+ handles. insert ( 0i32 , Box :: new ( io:: stdin ( ) ) as Box < dyn FileDescriptor < ' _ > > ) ;
122+ handles. insert ( 1i32 , Box :: new ( io:: stdout ( ) ) as Box < dyn FileDescriptor < ' _ > > ) ;
123+ handles. insert ( 2i32 , Box :: new ( io:: stderr ( ) ) as Box < dyn FileDescriptor < ' _ > > ) ;
124+ FileHandler {
125+ handles
126+ }
127+ }
128+ }
129+
56130
57131// fd numbers 0, 1, and 2 are reserved for stdin, stdout, and stderr
58132const MIN_NORMAL_FILE_FD : i32 = 3 ;
@@ -485,7 +559,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
485559 let this = self . eval_context_mut ( ) ;
486560
487561 this. check_no_isolation ( "read" ) ?;
488- assert ! ( fd >= 3 ) ;
489562
490563 trace ! ( "Reading from FD {}, size {}" , fd, count) ;
491564
@@ -537,8 +610,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
537610 ) -> InterpResult < ' tcx , i64 > {
538611 let this = self . eval_context_mut ( ) ;
539612
540- this. check_no_isolation ( "write" ) ?;
541- assert ! ( fd >= 3 ) ;
613+ if fd >= 3 {
614+ this. check_no_isolation ( "write" ) ?;
615+ }
542616
543617 // Check that the *entire* buffer is actually valid memory.
544618 this. memory . check_ptr_access (
0 commit comments