@@ -4,6 +4,8 @@ use rustc::hir::def_id::DefId;
44use rustc:: mir;
55use syntax:: attr;
66
7+ use rand:: RngCore ;
8+
79use crate :: * ;
810
911impl < ' a , ' mir , ' tcx > EvalContextExt < ' a , ' mir , ' tcx > for crate :: MiriEvalContext < ' a , ' mir , ' tcx > { }
@@ -224,16 +226,26 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a + 'mir>: crate::MiriEvalContextExt<'
224226 }
225227
226228 "syscall" => {
227- // TODO: read `syscall` IDs like `sysconf` IDs and
228- // figure out some way to actually process some of them.
229- //
229+ let sys_getrandom = this. eval_path_scalar ( & [ "libc" , "SYS_getrandom" ] ) ?
230+ . expect ( "Failed to get libc::SYS_getrandom" )
231+ . to_usize ( this) ?;
232+
230233 // `libc::syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), GRND_NONBLOCK)`
231- // is called if a `HashMap` is created the regular way.
234+ // is called if a `HashMap` is created the regular way (e.g. HashMap<K, V>) .
232235 match this. read_scalar ( args[ 0 ] ) ?. to_usize ( this) ? {
233- 318 | 511 => {
234- return err ! ( Unimplemented (
235- "miri does not support random number generators" . to_owned( ) ,
236- ) )
236+ id if id == sys_getrandom => {
237+ let ptr = this. read_scalar ( args[ 1 ] ) ?. to_ptr ( ) ?;
238+ let len = this. read_scalar ( args[ 2 ] ) ?. to_usize ( this) ?;
239+
240+ // The only supported flags are GRND_RANDOM and GRND_NONBLOCK,
241+ // neither of which have any effect on our current PRNG
242+ let _flags = this. read_scalar ( args[ 3 ] ) ?. to_i32 ( ) ?;
243+
244+ let data = gen_random ( this, len as usize ) ?;
245+ this. memory_mut ( ) . get_mut ( ptr. alloc_id ) ?
246+ . write_bytes ( tcx, ptr, & data) ?;
247+
248+ this. write_scalar ( Scalar :: from_uint ( len, dest. layout . size ) , dest) ?;
237249 }
238250 id => {
239251 return err ! ( Unimplemented (
@@ -499,18 +511,13 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a + 'mir>: crate::MiriEvalContextExt<'
499511 ] ;
500512 let mut result = None ;
501513 for & ( path, path_value) in paths {
502- if let Ok ( instance) = this. resolve_path ( path) {
503- let cid = GlobalId {
504- instance,
505- promoted : None ,
506- } ;
507- let const_val = this. const_eval_raw ( cid) ?;
508- let const_val = this. read_scalar ( const_val. into ( ) ) ?;
509- let value = const_val. to_i32 ( ) ?;
510- if value == name {
514+ if let Some ( val) = this. eval_path_scalar ( path) ? {
515+ let val = val. to_i32 ( ) ?;
516+ if val == name {
511517 result = Some ( path_value) ;
512518 break ;
513519 }
520+
514521 }
515522 }
516523 if let Some ( result) = result {
@@ -757,6 +764,17 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a + 'mir>: crate::MiriEvalContextExt<'
757764 "GetCommandLineW" => {
758765 this. write_scalar ( Scalar :: Ptr ( this. machine . cmd_line . unwrap ( ) ) , dest) ?;
759766 }
767+ // The actual name of 'RtlGenRandom'
768+ "SystemFunction036" => {
769+ let ptr = this. read_scalar ( args[ 0 ] ) ?. to_ptr ( ) ?;
770+ let len = this. read_scalar ( args[ 1 ] ) ?. to_usize ( this) ?;
771+
772+ let data = gen_random ( this, len as usize ) ?;
773+ this. memory_mut ( ) . get_mut ( ptr. alloc_id ) ?
774+ . write_bytes ( tcx, ptr, & data) ?;
775+
776+ this. write_scalar ( Scalar :: from_bool ( true ) , dest) ?;
777+ }
760778
761779 // We can't execute anything else.
762780 _ => {
@@ -774,4 +792,42 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a + 'mir>: crate::MiriEvalContextExt<'
774792 fn write_null ( & mut self , dest : PlaceTy < ' tcx , Borrow > ) -> EvalResult < ' tcx > {
775793 self . eval_context_mut ( ) . write_scalar ( Scalar :: from_int ( 0 , dest. layout . size ) , dest)
776794 }
795+
796+ /// Evaluates the scalar at the specified path. Returns Some(val)
797+ /// if the path could be resolved, and None otherwise
798+ fn eval_path_scalar ( & mut self , path : & [ & str ] ) -> EvalResult < ' tcx , Option < ScalarMaybeUndef < stacked_borrows:: Borrow > > > {
799+ let this = self . eval_context_mut ( ) ;
800+ if let Ok ( instance) = this. resolve_path ( path) {
801+ let cid = GlobalId {
802+ instance,
803+ promoted : None ,
804+ } ;
805+ let const_val = this. const_eval_raw ( cid) ?;
806+ let const_val = this. read_scalar ( const_val. into ( ) ) ?;
807+ return Ok ( Some ( const_val) ) ;
808+ }
809+ return Ok ( None ) ;
810+ }
811+ }
812+
813+ fn gen_random < ' a , ' mir , ' tcx > (
814+ this : & mut MiriEvalContext < ' a , ' mir , ' tcx > ,
815+ len : usize ,
816+ ) -> Result < Vec < u8 > , EvalError < ' tcx > > {
817+
818+ match & mut this. machine . rng {
819+ Some ( rng) => {
820+ let mut data = vec ! [ 0 ; len] ;
821+ rng. fill_bytes ( & mut data) ;
822+ Ok ( data)
823+ }
824+ None => {
825+ err ! ( Unimplemented (
826+ "miri does not support gathering system entropy in deterministic mode!
827+ Use '-Zmiri-seed=<seed>' to enable random number generation.
828+ WARNING: Miri does *not* generate cryptographically secure entropy -
829+ do not use Miri to run any program that needs secure random number generation" . to_owned( ) ,
830+ ) )
831+ }
832+ }
777833}
0 commit comments