wasmer_wasix/syscalls/wasi/
random_get.rs

1use super::*;
2use crate::syscalls::*;
3
4const MAX_CHUNK_LEN: usize = 4 * 1024;
5
6/// ### `random_get()`
7/// Fill buffer with high-quality random data.  This function may be slow and block
8/// Inputs:
9/// - `void *buf`
10///     A pointer to a buffer where the random bytes will be written
11/// - `size_t buf_len`
12///     The number of bytes that will be written
13#[instrument(level = "trace", skip_all, fields(%buf_len), ret)]
14pub fn random_get<M: MemorySize>(
15    ctx: FunctionEnvMut<'_, WasiEnv>,
16    buf: WasmPtr<u8, M>,
17    buf_len: M::Offset,
18) -> Errno {
19    let buf_len64: u64 = buf_len.into();
20    if buf_len64 == 0 {
21        return Errno::Success;
22    }
23
24    let env = ctx.data();
25    let memory = unsafe { env.memory_view(&ctx) };
26    let buf_slice = wasi_try_mem!(buf.slice(&memory, buf_len));
27    // If the buffer is owned we cannot call .access() on it
28    // as that would trigger unbounded host allocation in JS.
29    if buf_slice.is_owned() {
30        let mut buffer = vec![0u8; MAX_CHUNK_LEN.min(buf_len64 as usize)];
31        let mut offset = 0u64;
32
33        while offset < buf_len64 {
34            let chunk_len = usize::min((buf_len64 - offset) as usize, buffer.len());
35            if getrandom::fill(&mut buffer[..chunk_len]).is_err() {
36                return Errno::Io;
37            }
38
39            let chunk = buf_slice.subslice(offset..offset + chunk_len as u64);
40            wasi_try_mem!(chunk.write_slice(&buffer[..chunk_len]));
41
42            offset += chunk_len as u64;
43        }
44    } else {
45        let mut buf = wasi_try_mem!(buf_slice.access());
46        if getrandom::fill(buf.as_mut()).is_err() {
47            return Errno::Io;
48        }
49    }
50
51    Errno::Success
52}