When running in an V8 environment where creating external buffers is not allowed, buffer memory gets corrupted.
Take the following Rust code (lib.rs):
use napi::{Env, JsArrayBuffer};
#[napi_derive::napi]
pub fn create_buffer(env: Env) -> napi::Result<JsArrayBuffer> {
let data = vec![0xDEu8, 0xAD, 0xBE, 0xEF];
let v = env.create_arraybuffer_with_data(data)?;
Ok(v.into_raw())
}
Running this in the NodeJS CLI correctly produces the correct buffer:
> const m = require("/path/to/module-from-above.node");
undefined
> m.createBuffer();
ArrayBuffer { [Uint8Contents]: <de ad be ef>, byteLength: 4 }
Running this in an electron CLI produces a corrupt buffer (electron -i):
> const m = require("/path/to/module-from-above.node");
undefined
> m.createBuffer();
ArrayBuffer { [Uint8Contents]: <de 00 00 00>, byteLength: 4 }
// Content should be <de ad be ef>, only the first byte got copied
This is happening due to a bug here:
|
ptr::swap(underlying_data.cast(), data_ptr); |
More specifically, std::ptr::swap swaps 2 structures from one place to another using their structure size. In this case this means swapping *mut u8, which copies exactly one byte. The correct usage would be std::ptr::copy_nonoverlapping (the swap is not needed because u8 is Copy).
This bug seems to exist in multiple places in different variants (for example, Env::create_arraybuffer_with_borrowed_data completly fails to copy data at all when external buffers are disabled).
When running in an V8 environment where creating external buffers is not allowed, buffer memory gets corrupted.
Take the following Rust code (lib.rs):
Running this in the NodeJS CLI correctly produces the correct buffer:
Running this in an electron CLI produces a corrupt buffer (
electron -i):This is happening due to a bug here:
napi-rs/crates/napi/src/env.rs
Line 464 in 80f37ee
More specifically,
std::ptr::swapswaps 2 structures from one place to another using their structure size. In this case this means swapping*mut u8, which copies exactly one byte. The correct usage would bestd::ptr::copy_nonoverlapping(the swap is not needed becauseu8isCopy).This bug seems to exist in multiple places in different variants (for example,
Env::create_arraybuffer_with_borrowed_datacompletly fails to copy data at all when external buffers are disabled).