1
1
use std:: convert:: TryFrom ;
2
+ use std:: io:: { self , Read , Write } ;
2
3
3
4
use log:: trace;
4
5
@@ -11,6 +12,7 @@ use shims::posix::fs::EvalContextExt as _;
11
12
use shims:: posix:: sync:: EvalContextExt as _;
12
13
use shims:: posix:: thread:: EvalContextExt as _;
13
14
15
+
14
16
impl < ' mir , ' tcx : ' mir > EvalContextExt < ' mir , ' tcx > for crate :: MiriEvalContext < ' mir , ' tcx > { }
15
17
pub trait EvalContextExt < ' mir , ' tcx : ' mir > : crate :: MiriEvalContextExt < ' mir , ' tcx > {
16
18
fn emulate_foreign_item_by_name (
@@ -67,10 +69,23 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
67
69
let buf = this. read_scalar ( buf) ?. not_undef ( ) ?;
68
70
let count = this. read_scalar ( count) ?. to_machine_usize ( this) ?;
69
71
let result = if fd == 0 {
70
- use std:: io:: { self , Read } ;
71
72
72
73
this. check_no_isolation ( "read" ) ?;
73
74
75
+ // We cap the number of read bytes to the largest
76
+ // value that we are able to fit in both the
77
+ // host's and target's `isize`. This saves us from
78
+ // having to handle overflows later.
79
+ let count = count. min ( this. machine_isize_max ( ) as u64 ) . min ( isize:: MAX as u64 ) ;
80
+ // This can never fail because `count` was capped
81
+ // to be smaller than `isize::MAX`.
82
+ let count = isize:: try_from ( count) . unwrap ( ) ;
83
+
84
+ // We want to read at most `count` bytes. We are
85
+ // sure that `count` is not negative because it
86
+ // was a target's `usize`. Also we are sure that
87
+ // its smaller than `usize::MAX` because it is a
88
+ // host's `isize`.
74
89
let mut buffer = vec ! [ 0 ; count as usize ] ;
75
90
let res = io:: stdin ( )
76
91
. read ( & mut buffer)
@@ -83,8 +98,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
83
98
this. memory . write_bytes ( buf, buffer) ?;
84
99
i64:: try_from ( bytes) . unwrap ( )
85
100
} ,
86
- // FIXME: set errno to appropriate value
87
- Err ( _) => -1 ,
101
+ Err ( e) => {
102
+ this. set_last_error_from_io_error ( e) ?;
103
+ -1
104
+ } ,
88
105
}
89
106
} else if fd == 1 || fd == 2 {
90
107
throw_unsup_format ! ( "cannot read from stdout/stderr" )
@@ -103,7 +120,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
103
120
throw_unsup_format ! ( "cannot write to stdin" )
104
121
} else if fd == 1 || fd == 2 {
105
122
// stdout/stderr
106
- use std:: io:: { self , Write } ;
107
123
108
124
let buf_cont = this. memory . read_bytes ( buf, Size :: from_bytes ( count) ) ?;
109
125
// We need to flush to make sure this actually appears on the screen
0 commit comments