@@ -150,7 +150,10 @@ impl FileDescription for io::Stdin {
150
150
helpers:: isolation_abort_error ( "`read` from stdin" ) ?;
151
151
}
152
152
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
+ }
154
157
}
155
158
156
159
fn is_tty ( & self , communicate_allowed : bool ) -> bool {
@@ -181,7 +184,10 @@ impl FileDescription for io::Stdout {
181
184
// the host -- there is no good in adding extra buffering
182
185
// here.
183
186
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
+ }
185
191
}
186
192
187
193
fn is_tty ( & self , communicate_allowed : bool ) -> bool {
@@ -207,7 +213,10 @@ impl FileDescription for io::Stderr {
207
213
// We allow writing to stderr even with isolation enabled.
208
214
// No need to flush, stderr is not buffered.
209
215
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
+ }
211
220
}
212
221
213
222
fn is_tty ( & self , communicate_allowed : bool ) -> bool {
@@ -234,8 +243,7 @@ impl FileDescription for NullOutput {
234
243
ecx : & mut MiriInterpCx < ' tcx > ,
235
244
) -> InterpResult < ' tcx > {
236
245
// 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)
239
247
}
240
248
}
241
249
@@ -655,46 +663,39 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
655
663
}
656
664
657
665
/// 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.
659
669
/// 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 (
663
672
& mut self ,
664
673
buf : Pointer ,
665
674
bytes : & [ u8 ] ,
666
- result : io :: Result < usize > ,
675
+ actual_read_size : usize ,
667
676
dest : & MPlaceTy < ' tcx > ,
668
677
) -> InterpResult < ' tcx > {
669
678
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 ( ( ) )
686
687
}
687
688
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 (
691
692
& mut self ,
692
- result : io :: Result < usize > ,
693
+ actual_write_size : usize ,
693
694
dest : & MPlaceTy < ' tcx > ,
694
695
) -> InterpResult < ' tcx > {
695
696
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) ?;
698
699
Ok ( ( ) )
699
700
}
700
701
}
0 commit comments