11use std:: convert:: TryFrom ;
2+ use std:: io:: { self , Read , Write } ;
23
34use log:: trace;
45
@@ -67,7 +68,37 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
6768 let buf = this. read_scalar ( buf) ?. not_undef ( ) ?;
6869 let count = this. read_scalar ( count) ?. to_machine_usize ( this) ?;
6970 let result = if fd == 0 {
70- throw_unsup_format ! ( "reading from stdin is not implemented" )
71+
72+ this. check_no_isolation ( "read" ) ?;
73+
74+ // We cap the number of read bytes to the largest
75+ // value that we are able to fit in both the
76+ // host's and target's `isize`. This saves us from
77+ // having to handle overflows later.
78+ let count = count. min ( this. machine_isize_max ( ) as u64 ) . min ( isize:: MAX as u64 ) ;
79+
80+ // We want to read at most `count` bytes. We are
81+ // sure that `count` is not negative because it
82+ // was a target's `usize`. Also we are sure that
83+ // its smaller than `usize::MAX` because it is a
84+ // host's `isize`.
85+ let mut buffer = vec ! [ 0 ; count as usize ] ;
86+ let res = io:: stdin ( )
87+ . read ( & mut buffer)
88+ // `Stdin::read` never returns a value larger
89+ // than `count`, so this cannot fail.
90+ . map ( |c| i64:: try_from ( c) . unwrap ( ) ) ;
91+
92+ match res {
93+ Ok ( bytes) => {
94+ this. memory . write_bytes ( buf, buffer) ?;
95+ i64:: try_from ( bytes) . unwrap ( )
96+ } ,
97+ Err ( e) => {
98+ this. set_last_error_from_io_error ( e) ?;
99+ -1
100+ } ,
101+ }
71102 } else if fd == 1 || fd == 2 {
72103 throw_unsup_format ! ( "cannot read from stdout/stderr" )
73104 } else {
@@ -85,7 +116,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
85116 throw_unsup_format ! ( "cannot write to stdin" )
86117 } else if fd == 1 || fd == 2 {
87118 // stdout/stderr
88- use std:: io:: { self , Write } ;
89119
90120 let buf_cont = this. memory . read_bytes ( buf, Size :: from_bytes ( count) ) ?;
91121 // We need to flush to make sure this actually appears on the screen
@@ -103,6 +133,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
103133 } ;
104134 match res {
105135 Ok ( n) => i64:: try_from ( n) . unwrap ( ) ,
136+ // FIXME: set errno to appropriate value
106137 Err ( _) => -1 ,
107138 }
108139 } else {
0 commit comments