Skip to content

Commit

Permalink
Remove buffer zeroing from Node.js implementation (#315)
Browse files Browse the repository at this point in the history
We can use
[`Uint8Array::view_mut_raw`](https://rustwasm.github.io/wasm-bindgen/api/js_sys/struct.Uint8Array.html#method.view_mut_raw)
which was
[added](rustwasm/wasm-bindgen#1850) in version
`0.2.54` of `wasm-bindgen`. This method was introduced to deal with
uninitialized memory, see the Safety comment for more info.

Signed-off-by: Joe Richey <joerichey@google.com>
  • Loading branch information
josephlr authored Oct 23, 2022
1 parent 710b24d commit 52a4c3c
Showing 1 changed file with 14 additions and 7 deletions.
21 changes: 14 additions & 7 deletions src/js.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use crate::{util::uninit_slice_fill_zero, Error};
use crate::Error;

extern crate std;
use std::{mem::MaybeUninit, thread_local};
Expand Down Expand Up @@ -36,12 +36,19 @@ pub(crate) fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error>

match source {
RngSource::Node(n) => {
// XXX(perf): `random_fill_sync` requires a `&mut [u8]` so we
// have to ensure the memory in `dest` is initialized.
let dest = uninit_slice_fill_zero(dest);

for chunk in dest.chunks_mut(NODE_MAX_BUFFER_SIZE) {
if n.random_fill_sync(chunk).is_err() {
// SAFETY: chunk is never used directly, the memory is only
// modified via the Uint8Array view, which is passed
// directly to JavaScript. Also, crypto.randomFillSync does
// not resize the buffer. We know the length is less than
// u32::MAX because of the chunking above.
// Note that this uses the fact that JavaScript doesn't
// have a notion of "uninitialized memory", this is purely
// a Rust/C/C++ concept.
let res = n.random_fill_sync(unsafe {
Uint8Array::view_mut_raw(chunk.as_mut_ptr() as *mut u8, chunk.len())
});
if res.is_err() {
return Err(Error::NODE_RANDOM_FILL_SYNC);
}
}
Expand Down Expand Up @@ -130,7 +137,7 @@ extern "C" {
type NodeCrypto;
// crypto.randomFillSync()
#[wasm_bindgen(method, js_name = randomFillSync, catch)]
fn random_fill_sync(this: &NodeCrypto, buf: &mut [u8]) -> Result<(), JsValue>;
fn random_fill_sync(this: &NodeCrypto, buf: Uint8Array) -> Result<(), JsValue>;

// Ideally, we would just use `fn require(s: &str)` here. However, doing
// this causes a Webpack warning. So we instead return the function itself
Expand Down

0 comments on commit 52a4c3c

Please sign in to comment.