11use std:: convert:: TryFrom ;
2+ use std:: io:: { self , Read , Write } ;
23
34use log:: trace;
45
@@ -11,6 +12,7 @@ use shims::posix::fs::EvalContextExt as _;
1112use shims:: posix:: sync:: EvalContextExt as _;
1213use shims:: posix:: thread:: EvalContextExt as _;
1314
15+
1416impl < ' mir , ' tcx : ' mir > EvalContextExt < ' mir , ' tcx > for crate :: MiriEvalContext < ' mir , ' tcx > { }
1517pub trait EvalContextExt < ' mir , ' tcx : ' mir > : crate :: MiriEvalContextExt < ' mir , ' tcx > {
1618 fn emulate_foreign_item_by_name (
@@ -67,10 +69,23 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
6769 let buf = this. read_scalar ( buf) ?. not_undef ( ) ?;
6870 let count = this. read_scalar ( count) ?. to_machine_usize ( this) ?;
6971 let result = if fd == 0 {
70- use std:: io:: { self , Read } ;
7172
7273 this. check_no_isolation ( "read" ) ?;
7374
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`.
7489 let mut buffer = vec ! [ 0 ; count as usize ] ;
7590 let res = io:: stdin ( )
7691 . read ( & mut buffer)
@@ -83,8 +98,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
8398 this. memory . write_bytes ( buf, buffer) ?;
8499 i64:: try_from ( bytes) . unwrap ( )
85100 } ,
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+ } ,
88105 }
89106 } else if fd == 1 || fd == 2 {
90107 throw_unsup_format ! ( "cannot read from stdout/stderr" )
@@ -103,7 +120,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
103120 throw_unsup_format ! ( "cannot write to stdin" )
104121 } else if fd == 1 || fd == 2 {
105122 // stdout/stderr
106- use std:: io:: { self , Write } ;
107123
108124 let buf_cont = this. memory . read_bytes ( buf, Size :: from_bytes ( count) ) ?;
109125 // We need to flush to make sure this actually appears on the screen
0 commit comments