Skip to content

Commit ac3bada

Browse files
committed
add a test for the getrandom fallback
1 parent 8e15021 commit ac3bada

1 file changed

Lines changed: 56 additions & 0 deletions

File tree

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
//@ only-linux
2+
//@ run-pass
3+
4+
#![feature(random)]
5+
#![feature(rustc_private)]
6+
7+
extern crate libc;
8+
9+
use std::ffi::{c_void, c_uint, c_int};
10+
use std::random::{SystemRng, Rng};
11+
use std::cell::Cell;
12+
use std::panic::catch_unwind;
13+
14+
thread_local! {
15+
static GETRANDOM_ERROR: Cell<c_int> = const { Cell::new(libc::ENOMEM) };
16+
}
17+
18+
// This interposes the symbol defined in the libc to return an error when we
19+
// want it to.
20+
#[unsafe(no_mangle)]
21+
fn getrandom(_buf: *const c_void, _size: usize, _flags: c_uint) -> isize {
22+
let errno = GETRANDOM_ERROR.get();
23+
unsafe { libc::__errno_location().write(errno) };
24+
-1
25+
}
26+
27+
fn main() {
28+
// Step one:
29+
// Test that the interposed symbol actually gets used by having it return an
30+
// error that makes `SystemRng` panic.
31+
GETRANDOM_ERROR.set(libc::ENOMEM);
32+
catch_unwind(|| {
33+
let mut buf = [0; 16];
34+
SystemRng.fill_bytes(&mut buf);
35+
}).expect_err("SystemRng should panic upon receiving ENOMEM from the interposed getrandom");
36+
37+
// Step two:
38+
// Emulate a missing `getrandom` by returning `ENOSYS`. This should excercise
39+
// the fallback code.
40+
GETRANDOM_ERROR.set(libc::ENOSYS);
41+
let mut buf = [0; 16];
42+
SystemRng.fill_bytes(&mut buf);
43+
44+
// Smoke check that the buffer was actually filled. It is possible for this
45+
// to spuriously fail, but the likelyhood of that happening is 1 in 2^256.
46+
assert_ne!(buf, [0; 16]);
47+
48+
// And lastly, check that the random pool has been initialized by manually
49+
// calling the getrandom syscall and checking that it does not block. This
50+
// is unlikely to catch any issues since the randomness pool is nearly always
51+
// initialized, but who knows.
52+
let r = unsafe {
53+
libc::syscall(libc::SYS_getrandom, buf.as_mut_ptr(), buf.len(), libc::GRND_NONBLOCK)
54+
};
55+
assert_ne!(r, -1);
56+
}

0 commit comments

Comments
 (0)