Skip to content

Creating an array buffer with V8 Sandboxing enabled corrupts the buffer data #1919

@Janrupf

Description

@Janrupf

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).

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions