From 6c6fbefed7455bf903a9c299c18349c30d7082dd Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Fri, 27 Sep 2024 19:31:00 +0300 Subject: [PATCH] Add support for `wasm32-wasip1` and `wasm32-wasip2`, remove support for `wasm32-wasi` (#499) The `wasm32-wasi` target will be removed in Rust 1.84 (https://blog.rust-lang.org/2024/04/09/updates-to-rusts-wasi-targets.html) and existing users are encouraged to migrate to either `wasm32-wasip1`, or `wasm32-wasip2`. Strictly speaking, this is a breaking change despite affecting only deprecated target, so it's probably better to release it in `getrandom` v0.3. --- .cargo/config.toml | 4 ++- .github/workflows/tests.yml | 16 +++++++---- .github/workflows/workspace.yml | 10 ++++--- CHANGELOG.md | 5 ++++ Cargo.toml | 22 +++++++-------- src/lib.rs | 6 ++-- src/wasi.rs | 50 +++++++++++++++++++++++++++++++-- 7 files changed, 86 insertions(+), 27 deletions(-) diff --git a/.cargo/config.toml b/.cargo/config.toml index be3061ab..567208e3 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,7 +1,9 @@ # Allow normal use of "cargo run" and "cargo test" on these wasm32 platforms. [target.wasm32-unknown-unknown] runner = 'wasm-bindgen-test-runner' -[target.wasm32-wasi] +[target.wasm32-wasip1] +runner = 'wasmtime' +[target.wasm32-wasip2] runner = 'wasmtime' # Just run on node by default (that's where emscripten is tested) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 963a0fcb..c4e1cf53 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -274,21 +274,25 @@ jobs: run: cargo test --no-run -Z build-std=std,panic_abort --target=wasm64-unknown-unknown --features=js wasi-tests: - name: WASI Test + name: WASI Tests runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@stable + - uses: dtolnay/rust-toolchain@master with: - targets: wasm32-wasi - - name: Install precompiled wasmtime + toolchain: nightly # TODO: Use stable after 1.82 is released as stable + targets: wasm32-wasip1,wasm32-wasip2 + - name: Install Wasmtime run: | - VERSION=v2.0.0 + VERSION=v24.0.0 URL=https://github.com/bytecodealliance/wasmtime/releases/download/${VERSION}/wasmtime-${VERSION}-x86_64-linux.tar.xz wget -O - $URL | tar -xJ --strip-components=1 -C ~/.cargo/bin wasmtime --version - uses: Swatinem/rust-cache@v2 - - run: cargo test --target wasm32-wasi + - name: WASI 0.1 Test + run: cargo test --target wasm32-wasip1 + - name: WASI 0.2 Test + run: cargo test --target wasm32-wasip2 build-tier2: name: Tier 2 Build diff --git a/.github/workflows/workspace.yml b/.github/workflows/workspace.yml index 5c029aad..db7b1568 100644 --- a/.github/workflows/workspace.yml +++ b/.github/workflows/workspace.yml @@ -23,7 +23,7 @@ jobs: # Fixed Nigthly version is used to prevent # CI failures which are not relevant to PR changes # on introduction of new Clippy lints. - toolchain: nightly-2024-06-11 + toolchain: nightly-2024-09-04 components: clippy,rust-src - name: std feature run: cargo clippy --features std @@ -59,8 +59,10 @@ jobs: run: cargo clippy -Zbuild-std=core --target x86_64-unknown-redox - name: VxWorks (vxworks.rs) run: cargo clippy -Zbuild-std=core --target x86_64-wrs-vxworks - - name: WASI (wasi.rs) - run: cargo clippy -Zbuild-std=core --target wasm32-wasip2 + - name: WASI preview 1 (wasi.rs) + run: cargo clippy -Zbuild-std=core --target wasm32-wasip1 + - name: WASI preview 2 (wasi.rs) + run: cargo clippy -Zbuild-std=core,alloc --target wasm32-wasip2 - name: Windows 7 (windows7.rs) run: cargo clippy -Zbuild-std=core --target x86_64-win7-windows-msvc - name: Windows (windows.rs) @@ -86,7 +88,7 @@ jobs: - uses: dtolnay/rust-toolchain@master with: # We need Nightly for doc_auto_cfg - toolchain: nightly-2024-06-11 + toolchain: nightly-2024-09-04 - uses: Swatinem/rust-cache@v2 - name: Generate Docs env: diff --git a/CHANGELOG.md b/CHANGELOG.md index d32a369e..fc39b075 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,8 +8,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Breaking Changes - Update MSRV to 1.38 [#425] +- Remove support of the `wasm32-wasi` target (use `wasm32-wasip1` or `wasm32-wasip2` instead) [#499] + +### Added +- `wasm32-wasip1` and `wasm32-wasip2` support [#499] [#425]: https://github.com/rust-random/getrandom/pull/425 +[#499]: https://github.com/rust-random/getrandom/pull/499 ## [0.2.15] - 2024-05-06 ### Added diff --git a/Cargo.toml b/Cargo.toml index 6ba57f37..34dbd3a5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,9 +21,12 @@ core = { version = "1.0", optional = true, package = "rustc-std-workspace-core" [target.'cfg(unix)'.dependencies] libc = { version = "0.2.154", default-features = false } -[target.'cfg(target_os = "wasi")'.dependencies] +[target.'cfg(all(target_arch = "wasm32", target_os = "wasi", target_env = "p1"))'.dependencies] wasi = { version = "0.11", default-features = false } +[target.'cfg(all(target_arch = "wasm32", target_os = "wasi", target_env = "p2"))'.dependencies] +wasi = { version = "0.13", default-features = false } + [target.'cfg(all(windows, not(target_vendor = "win7")))'.dependencies] windows-targets = "0.52" @@ -46,10 +49,7 @@ js = ["wasm-bindgen", "js-sys"] # Feature to enable custom RNG implementations custom = [] # Unstable feature to support being a libstd dependency -rustc-dep-of-std = [ - "compiler_builtins", - "core", -] +rustc-dep-of-std = ["compiler_builtins", "core"] # Unstable/test-only feature to run wasm-bindgen tests in a browser test-in-browser = [] @@ -64,10 +64,10 @@ rustdoc-args = ["--cfg", "docsrs"] # workaround for https://github.com/cross-rs/cross/issues/1345 [package.metadata.cross.target.x86_64-unknown-netbsd] pre-build = [ - "mkdir -p /tmp/netbsd", - "curl https://cdn.netbsd.org/pub/NetBSD/NetBSD-9.2/amd64/binary/sets/base.tar.xz -O", - "tar -C /tmp/netbsd -xJf base.tar.xz", - "cp /tmp/netbsd/usr/lib/libexecinfo.so /usr/local/x86_64-unknown-netbsd/lib", - "rm base.tar.xz", - "rm -rf /tmp/netbsd", + "mkdir -p /tmp/netbsd", + "curl https://cdn.netbsd.org/pub/NetBSD/NetBSD-9.2/amd64/binary/sets/base.tar.xz -O", + "tar -C /tmp/netbsd -xJf base.tar.xz", + "cp /tmp/netbsd/usr/lib/libexecinfo.so /usr/local/x86_64-unknown-netbsd/lib", + "rm base.tar.xz", + "rm -rf /tmp/netbsd", ] diff --git a/src/lib.rs b/src/lib.rs index f5e13c36..97622ecf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,7 +24,8 @@ //! | VxWorks | `*‑wrs‑vxworks‑*` | `randABytes` after checking entropy pool initialization with `randSecure` //! | ESP-IDF | `*‑espidf` | [`esp_fill_random`] //! | Emscripten | `*‑emscripten` | [`getentropy`][13] -//! | WASI | `wasm32‑wasi` | [`random_get`] +//! | WASI 0.1 | `wasm32‑wasip1` | [`random_get`] +//! | WASI 0.2 | `wasm32‑wasip2` | [`get-random-u64`] //! | 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 | `*-nintendo-3ds` | [`getrandom`][18] @@ -191,7 +192,8 @@ //! [`cprng_draw`]: https://fuchsia.dev/fuchsia-src/zircon/syscalls/cprng_draw //! [`crypto.randomFillSync`]: https://nodejs.org/api/crypto.html#cryptorandomfillsyncbuffer-offset-size //! [`esp_fill_random`]: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/random.html#_CPPv415esp_fill_randomPv6size_t -//! [`random_get`]: https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#-random_getbuf-pointeru8-buf_len-size---errno +//! [`random_get`]: https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-random_getbuf-pointeru8-buf_len-size---errno +//! [`get-random-u64`]: https://github.com/WebAssembly/WASI/blob/v0.2.1/wasip2/random/random.wit#L23-L28 //! [WebAssembly support]: #webassembly-support //! [`wasm-bindgen`]: https://github.com/rustwasm/wasm-bindgen //! [`module`]: https://rustwasm.github.io/wasm-bindgen/reference/attributes/on-js-imports/module.html diff --git a/src/wasi.rs b/src/wasi.rs index 10d8ae79..77bc9531 100644 --- a/src/wasi.rs +++ b/src/wasi.rs @@ -1,9 +1,53 @@ -//! Implementation for WASI +//! Implementation for WASI (preview 1 and 2) +//! +//! `target_env = "p1"` was introduced only in Rust 1.80, so on earlier compiler versions this +//! code will result in a compilation error. use crate::Error; use core::mem::MaybeUninit; -use wasi::random_get; +#[cfg(not(any(target_env = "p1", target_env = "p2")))] +compile_error!( + "Unknown version of WASI (only previews 1 and 2 are supported) \ + or Rust version older than 1.80 was used" +); + +#[cfg(target_env = "p1")] pub fn getrandom_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { - unsafe { random_get(dest.as_mut_ptr().cast::(), dest.len()) } + unsafe { wasi::random_get(dest.as_mut_ptr().cast::(), dest.len()) } .map_err(|e| Error::from_os_error(e.raw().into())) } + +#[cfg(target_env = "p2")] +pub fn getrandom_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { + use core::ptr::copy_nonoverlapping; + use wasi::random::random::get_random_u64; + + let (prefix, chunks, suffix) = unsafe { dest.align_to_mut::>() }; + + // We use `get_random_u64` instead of `get_random_bytes` because the latter creates + // an allocation due to the Wit IDL [restrictions][0]. This should be fine since + // the main use case of `getrandom` is seed generation. + // + // [0]: https://github.com/WebAssembly/wasi-random/issues/27 + if !prefix.is_empty() { + let val = get_random_u64(); + let src = (&val as *const u64).cast(); + unsafe { + copy_nonoverlapping(src, prefix.as_mut_ptr(), prefix.len()); + } + } + + for dst in chunks { + dst.write(get_random_u64()); + } + + if !suffix.is_empty() { + let val = get_random_u64(); + let src = (&val as *const u64).cast(); + unsafe { + copy_nonoverlapping(src, suffix.as_mut_ptr(), suffix.len()); + } + } + + Ok(()) +}