@@ -150,7 +150,10 @@ impl FileDescription for io::Stdin {
150150 helpers:: isolation_abort_error ( "`read` from stdin" ) ?;
151151 }
152152 let result = Read :: read ( & mut { self } , & mut bytes) ;
153- ecx. return_read_bytes_and_count ( ptr, & bytes, result, dest)
153+ match result {
154+ Ok ( read_size) => ecx. return_read_success ( ptr, & bytes, read_size, dest) ,
155+ Err ( e) => ecx. set_last_error_and_return ( e, dest) ,
156+ }
154157 }
155158
156159 fn is_tty ( & self , communicate_allowed : bool ) -> bool {
@@ -181,7 +184,10 @@ impl FileDescription for io::Stdout {
181184 // the host -- there is no good in adding extra buffering
182185 // here.
183186 io:: stdout ( ) . flush ( ) . unwrap ( ) ;
184- ecx. return_written_byte_count_or_error ( result, dest)
187+ match result {
188+ Ok ( write_size) => ecx. return_write_success ( write_size, dest) ,
189+ Err ( e) => ecx. set_last_error_and_return ( e, dest) ,
190+ }
185191 }
186192
187193 fn is_tty ( & self , communicate_allowed : bool ) -> bool {
@@ -207,7 +213,10 @@ impl FileDescription for io::Stderr {
207213 // We allow writing to stderr even with isolation enabled.
208214 // No need to flush, stderr is not buffered.
209215 let result = Write :: write ( & mut { self } , bytes) ;
210- ecx. return_written_byte_count_or_error ( result, dest)
216+ match result {
217+ Ok ( write_size) => ecx. return_write_success ( write_size, dest) ,
218+ Err ( e) => ecx. set_last_error_and_return ( e, dest) ,
219+ }
211220 }
212221
213222 fn is_tty ( & self , communicate_allowed : bool ) -> bool {
@@ -234,8 +243,7 @@ impl FileDescription for NullOutput {
234243 ecx : & mut MiriInterpCx < ' tcx > ,
235244 ) -> InterpResult < ' tcx > {
236245 // We just don't write anything, but report to the user that we did.
237- let result = Ok ( len) ;
238- ecx. return_written_byte_count_or_error ( result, dest)
246+ ecx. return_write_success ( len, dest)
239247 }
240248}
241249
@@ -655,46 +663,39 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
655663 }
656664
657665 /// Helper to implement `FileDescription::read`:
658- /// `result` should be the return value of some underlying `read` call that used `bytes` as its output buffer.
666+ /// This is only used when `read` is successful.
667+ /// `actual_read_size` should be the return value of some underlying `read` call that used
668+ /// `bytes` as its output buffer.
659669 /// The length of `bytes` must not exceed either the host's or the target's `isize`.
660- /// If `Result` indicates success, `bytes` is written to `buf` and the size is written to `dest`.
661- /// Otherwise, `-1` is written to `dest` and the last libc error is set appropriately.
662- fn return_read_bytes_and_count (
670+ /// `bytes` is written to `buf` and the size is written to `dest`.
671+ fn return_read_success (
663672 & mut self ,
664673 buf : Pointer ,
665674 bytes : & [ u8 ] ,
666- result : io :: Result < usize > ,
675+ actual_read_size : usize ,
667676 dest : & MPlaceTy < ' tcx > ,
668677 ) -> InterpResult < ' tcx > {
669678 let this = self . eval_context_mut ( ) ;
670- match result {
671- Ok ( read_bytes) => {
672- // If reading to `bytes` did not fail, we write those bytes to the buffer.
673- // Crucially, if fewer than `bytes.len()` bytes were read, only write
674- // that much into the output buffer!
675- this. write_bytes_ptr ( buf, bytes[ ..read_bytes] . iter ( ) . copied ( ) ) ?;
676- // The actual read size is always less than what got originally requested so this cannot fail.
677- this. write_int ( u64:: try_from ( read_bytes) . unwrap ( ) , dest) ?;
678- Ok ( ( ) )
679- }
680- Err ( e) => {
681- this. set_last_error_from_io_error ( e) ?;
682- this. write_int ( -1 , dest) ?;
683- Ok ( ( ) )
684- }
685- }
679+ // If reading to `bytes` did not fail, we write those bytes to the buffer.
680+ // Crucially, if fewer than `bytes.len()` bytes were read, only write
681+ // that much into the output buffer!
682+ this. write_bytes_ptr ( buf, bytes[ ..actual_read_size] . iter ( ) . copied ( ) ) ?;
683+
684+ // The actual read size is always less than what got originally requested so this cannot fail.
685+ this. write_int ( u64:: try_from ( actual_read_size) . unwrap ( ) , dest) ?;
686+ Ok ( ( ) )
686687 }
687688
688- /// This function writes the number of written bytes (given in `result`) to `dest`, or sets the
689- /// last libc error and writes -1 to dest.
690- fn return_written_byte_count_or_error (
689+ /// Helper to implement `FileDescription::write`:
690+ /// This function is only used when `write` is successful, and writes `actual_write_size` to ` dest`
691+ fn return_write_success (
691692 & mut self ,
692- result : io :: Result < usize > ,
693+ actual_write_size : usize ,
693694 dest : & MPlaceTy < ' tcx > ,
694695 ) -> InterpResult < ' tcx > {
695696 let this = self . eval_context_mut ( ) ;
696- let result = this. try_unwrap_io_result ( result . map ( |c| i64 :: try_from ( c ) . unwrap ( ) ) ) ? ;
697- this. write_int ( result , dest) ?;
697+ // The actual write size is always less than what got originally requested so this cannot fail.
698+ this. write_int ( u64 :: try_from ( actual_write_size ) . unwrap ( ) , dest) ?;
698699 Ok ( ( ) )
699700 }
700701}
0 commit comments