diff --git a/src/ffi/data.cc b/src/ffi/data.cc index dbeba94cd1b9..ad92caf716ea 100644 --- a/src/ffi/data.cc +++ b/src/ffi/data.cc @@ -662,7 +662,7 @@ void ToArrayBuffer(const FunctionCallbackInfo& args) { if (copy) { std::unique_ptr store = ArrayBuffer::NewBackingStore(isolate, len); - memcpy(store->Data(), reinterpret_cast(ptr), len); + if (len > 0) memcpy(store->Data(), reinterpret_cast(ptr), len); ab = ArrayBuffer::New(isolate, std::move(store)); } else { std::unique_ptr store = ArrayBuffer::NewBackingStore( @@ -740,7 +740,9 @@ void ExportBytes(const FunctionCallbackInfo& args) { return; } - std::memcpy(reinterpret_cast(ptr), view.data(), view.length()); + if (view.length() > 0) { + std::memcpy(reinterpret_cast(ptr), view.data(), view.length()); + } } void GetRawPointer(const FunctionCallbackInfo& args) { diff --git a/test/ffi/test-ffi-memory.js b/test/ffi/test-ffi-memory.js index 53fe3928029b..3ed1dbcb1176 100644 --- a/test/ffi/test-ffi-memory.js +++ b/test/ffi/test-ffi-memory.js @@ -243,6 +243,14 @@ test('ffi toString returns null for a null pointer', () => { assert.strictEqual(ffi.toString(0n), null); }); +test('ffi accepts zero-length copies through a null pointer', () => { + assert.strictEqual(ffi.toBuffer(0n, 0).length, 0); + assert.strictEqual(ffi.toArrayBuffer(0n, 0).byteLength, 0); + assert.strictEqual(ffi.exportBuffer(Buffer.alloc(0), 0n, 0), undefined); + assert.strictEqual(ffi.exportArrayBuffer(new ArrayBuffer(0), 0n, 0), undefined); + assert.strictEqual(ffi.exportArrayBufferView(new Uint8Array(0), 0n, 0), undefined); +}); + test('ffi validates memory access arguments', () => { withAllocations(common.mustCall((alloc) => { const ptr = alloc(8);