diff --git a/ci.sh b/ci.sh index f0917556c6..ff45dc6a42 100755 --- a/ci.sh +++ b/ci.sh @@ -108,7 +108,7 @@ case $HOST_TARGET in MIRI_TEST_TARGET=aarch64-unknown-linux-gnu run_tests MIRI_TEST_TARGET=aarch64-apple-darwin run_tests MIRI_TEST_TARGET=i686-pc-windows-gnu run_tests - MIRI_TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple pthreads atomic env/var + MIRI_TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple pthreads libc-getentropy atomic env/var MIRI_TEST_TARGET=aarch64-linux-android run_tests_minimal hello integer vec panic/panic MIRI_TEST_TARGET=wasm32-wasi run_tests_minimal no_std integer strings wasm MIRI_TEST_TARGET=wasm32-unknown-unknown run_tests_minimal no_std integer strings wasm diff --git a/src/shims/unix/freebsd/foreign_items.rs b/src/shims/unix/freebsd/foreign_items.rs index 96e322c4cf..f81710a41a 100644 --- a/src/shims/unix/freebsd/foreign_items.rs +++ b/src/shims/unix/freebsd/foreign_items.rs @@ -47,6 +47,23 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.read_scalar(len)?, )?; } + "getentropy" => { + let [buf, bufsize] = + this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + let buf = this.read_pointer(buf)?; + let bufsize = this.read_target_usize(bufsize)?; + + // getentropy sets errno to EIO when the buffer size exceeds 256 bytes. + // https://man.freebsd.org/cgi/man.cgi?query=getentropy&sektion=3&format=html + if bufsize > 256 { + let err = this.eval_libc("EIO"); + this.set_last_error(err)?; + this.write_scalar(Scalar::from_i32(-1), dest)? + } else { + this.gen_random(buf, bufsize)?; + this.write_scalar(Scalar::from_i32(0), dest)?; + } + } // errno "__error" => { diff --git a/tests/pass-dep/shims/libc-getentropy.rs b/tests/pass-dep/shims/libc-getentropy.rs new file mode 100644 index 0000000000..468727f70e --- /dev/null +++ b/tests/pass-dep/shims/libc-getentropy.rs @@ -0,0 +1,11 @@ +//@only-target-freebsd + +fn main() { + let mut buf1 = [0u8; 256]; + let mut buf2 = [0u8; 257]; + unsafe { + assert_eq!(libc::getentropy(buf1.as_mut_ptr() as *mut libc::c_void, buf1.len()), 0); + assert_eq!(libc::getentropy(buf2.as_mut_ptr() as *mut libc::c_void, buf2.len()), -1); + assert_eq!(std::io::Error::last_os_error().raw_os_error().unwrap(), libc::EIO); + } +}