@@ -27,6 +27,8 @@ fn is_dyn_sym(name: &str, target_os: &str) -> bool {
2727 // `signal` is set up as a weak symbol in `init_extern_statics` (on Android) so we might as
2828 // well allow it in `dlsym`.
2929 "signal" => true ,
30+ // needed at least on macOS to avoid file-based fallback in getrandom
31+ "getentropy" => true ,
3032 // Give specific OSes a chance to allow their symbols.
3133 _ =>
3234 match target_os {
@@ -525,6 +527,34 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
525527 let result = this. getpid ( ) ?;
526528 this. write_scalar ( Scalar :: from_i32 ( result) , dest) ?;
527529 }
530+ "getentropy" => {
531+ // This function is non-standard but exists with the same signature and behavior on
532+ // Linux, macOS, and FreeBSD.
533+ if !matches ! ( & * this. tcx. sess. target. os, "linux" | "macos" | "freebsd" ) {
534+ throw_unsup_format ! (
535+ "`getentropy` is not supported on {}" ,
536+ this. tcx. sess. target. os
537+ ) ;
538+ }
539+
540+ let [ buf, bufsize] =
541+ this. check_shim ( abi, Abi :: C { unwind : false } , link_name, args) ?;
542+ let buf = this. read_pointer ( buf) ?;
543+ let bufsize = this. read_target_usize ( bufsize) ?;
544+
545+ // getentropy sets errno to EIO when the buffer size exceeds 256 bytes.
546+ // FreeBSD: https://man.freebsd.org/cgi/man.cgi?query=getentropy&sektion=3&format=html
547+ // Linux: https://man7.org/linux/man-pages/man3/getentropy.3.html
548+ // macOS: https://keith.github.io/xcode-man-pages/getentropy.2.html
549+ if bufsize > 256 {
550+ let err = this. eval_libc ( "EIO" ) ;
551+ this. set_last_error ( err) ?;
552+ this. write_scalar ( Scalar :: from_i32 ( -1 ) , dest) ?
553+ } else {
554+ this. gen_random ( buf, bufsize) ?;
555+ this. write_scalar ( Scalar :: from_i32 ( 0 ) , dest) ?;
556+ }
557+ }
528558
529559 // Incomplete shims that we "stub out" just to get pre-main initialization code to work.
530560 // These shims are enabled only when the caller is in the standard library.
@@ -594,7 +624,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
594624 this. write_int ( super :: UID , dest) ?;
595625 }
596626
597- "getpwuid_r" if this. frame_in_std ( ) => {
627+ "getpwuid_r"
628+ if this. frame_in_std ( ) => {
598629 let [ uid, pwd, buf, buflen, result] =
599630 this. check_shim ( abi, Abi :: C { unwind : false } , link_name, args) ?;
600631 this. check_no_isolation ( "`getpwuid_r`" ) ?;
0 commit comments