diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 0bcfe33f..aeaefd7a 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -219,6 +219,24 @@ jobs: - name: Test (custom getrandom) run: cargo test --target=wasm32-unknown-unknown --features=custom + wasm64-tests: + name: WASM memory64 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: nightly + components: rust-src + override: true + - uses: Swatinem/rust-cache@v1 + - name: Build and Link tests (build-std) + # This target is Tier 3, so we have to build libstd ourselves. + # We currently cannot run these tests because wasm-bindgen-test-runner + # does not yet support memory64. + run: cargo test --no-run -Z build-std=std,panic_abort --target=wasm64-unknown-unknown --features=js + wasi-tests: name: WASI test runs-on: ubuntu-latest diff --git a/Cargo.toml b/Cargo.toml index 320aa581..35408b83 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,10 +23,10 @@ libc = { version = "0.2.128", default-features = false } [target.'cfg(target_os = "wasi")'.dependencies] wasi = { version = "0.11", default-features = false } -[target.'cfg(all(target_arch = "wasm32", target_os = "unknown"))'.dependencies] +[target.'cfg(all(any(target_arch = "wasm32", target_arch = "wasm64"), target_os = "unknown"))'.dependencies] wasm-bindgen = { version = "0.2.62", default-features = false, optional = true } js-sys = { version = "0.3", optional = true } -[target.'cfg(all(target_arch = "wasm32", target_os = "unknown"))'.dev-dependencies] +[target.'cfg(all(any(target_arch = "wasm32", target_arch = "wasm64"), target_os = "unknown"))'.dev-dependencies] wasm-bindgen-test = "0.3.18" [features] @@ -34,7 +34,7 @@ wasm-bindgen-test = "0.3.18" std = [] # Feature to enable fallback RDRAND-based implementation on x86/x86_64 rdrand = [] -# Feature to enable JavaScript bindings on wasm32-unknown-unknown +# Feature to enable JavaScript bindings on wasm*-unknown-unknown js = ["wasm-bindgen", "js-sys"] # Feature to enable custom RNG implementations custom = [] diff --git a/src/js.rs b/src/js.rs index 7b9ae313..e692a1bd 100644 --- a/src/js.rs +++ b/src/js.rs @@ -16,6 +16,8 @@ use wasm_bindgen::{prelude::wasm_bindgen, JsCast, JsValue}; // Size of our temporary Uint8Array buffer used with WebCrypto methods // Maximum is 65536 bytes see https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues const WEB_CRYPTO_BUFFER_SIZE: usize = 256; +// Node.js's crypto.randomFillSync requires the size to be less than 2**31. +const NODE_MAX_BUFFER_SIZE: usize = (1 << 31) - 1; enum RngSource { Node(NodeCrypto), @@ -38,8 +40,10 @@ pub(crate) fn getrandom_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> // have to ensure the memory in `dest` is initialized. let dest = uninit_slice_fill_zero(dest); - if n.random_fill_sync(dest).is_err() { - return Err(Error::NODE_RANDOM_FILL_SYNC); + for chunk in dest.chunks_mut(NODE_MAX_BUFFER_SIZE) { + if n.random_fill_sync(chunk).is_err() { + return Err(Error::NODE_RANDOM_FILL_SYNC); + } } } RngSource::Web(crypto, buf) => { diff --git a/src/lib.rs b/src/lib.rs index 36a49c01..6f9fcd8a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -30,7 +30,7 @@ //! | ESP-IDF | `*‑espidf` | [`esp_fill_random`] //! | Emscripten | `*‑emscripten` | `/dev/urandom` (identical to `/dev/random`) //! | WASI | `wasm32‑wasi` | [`random_get`] -//! | Web Browser and Node.js | `wasm32‑*‑unknown` | [`Crypto.getRandomValues`] if available, then [`crypto.randomFillSync`] if on Node.js, see [WebAssembly support] +//! | Web Browser and Node.js | `wasm*‑*‑unknown` | [`Crypto.getRandomValues`] if available, then [`crypto.randomFillSync`] if on Node.js, see [WebAssembly support] //! | SOLID | `*-kmc-solid_*` | `SOLID_RNG_SampleRandomBytes` //! | Nintendo 3DS | `armv6k-nintendo-3ds` | [`getrandom`][1] //! @@ -262,12 +262,14 @@ cfg_if! { any(target_arch = "x86_64", target_arch = "x86")))] { #[path = "rdrand.rs"] mod imp; } else if #[cfg(all(feature = "js", - target_arch = "wasm32", target_os = "unknown"))] { + any(target_arch = "wasm32", target_arch = "wasm64"), + target_os = "unknown"))] { #[path = "js.rs"] mod imp; } else if #[cfg(feature = "custom")] { use custom as imp; - } else if #[cfg(all(target_arch = "wasm32", target_os = "unknown"))] { - compile_error!("the wasm32-unknown-unknown target is not supported by \ + } else if #[cfg(all(any(target_arch = "wasm32", target_arch = "wasm64"), + target_os = "unknown"))] { + compile_error!("the wasm*-unknown-unknown targets are not supported by \ default, you may need to enable the \"js\" feature. \ For more information see: \ https://docs.rs/getrandom/#webassembly-support");