Skip to content

Commit

Permalink
Properly test, reproduce, and fix the multiple non-null-pointer exter…
Browse files Browse the repository at this point in the history
…nal empty buffer situation that parcel often generates, #161
  • Loading branch information
kriszyp committed Apr 22, 2022
1 parent 69a7082 commit 1e0335e
Show file tree
Hide file tree
Showing 5 changed files with 19 additions and 4 deletions.
3 changes: 2 additions & 1 deletion native.js
Expand Up @@ -2,7 +2,7 @@ import { dirname, default as pathModule } from 'path';
import { fileURLToPath } from 'url';
import { createRequire } from 'module';

export let Env, Txn, Dbi, Compression, Cursor, getAddress, clearKeptObjects, setGlobalBuffer,
export let Env, Txn, Dbi, Compression, Cursor, getAddress, createBufferForAddress, clearKeptObjects, setGlobalBuffer,
require, arch, fs, os, onExit, tmpdir, lmdbError, path, EventEmitter, orderedBinary, MsgpackrEncoder, WeakLRUCache, setEnvMap, getEnvMap, getByBinary, detachBuffer, write, position, iterate, native, v8AccelerationEnabled = false;

require = createRequire(import.meta.url);
Expand Down Expand Up @@ -36,6 +36,7 @@ export function setNativeFunctions(externals) {
Dbi = externals.Dbi;
Compression = externals.Compression;
getAddress = externals.getAddress;
createBufferForAddress = externals.createBufferForAddress;
clearKeptObjects = externals.clearKeptObjects || function() {};
Cursor = externals.Cursor;
lmdbError = externals.lmdbError;
Expand Down
2 changes: 1 addition & 1 deletion src/lmdb-js.h
Expand Up @@ -141,7 +141,7 @@ bool getVersionAndUncompress(MDB_val &data, DbiWrap* dw);
int compareFast(const MDB_val *a, const MDB_val *b);
Value setGlobalBuffer(const CallbackInfo& info);
Value lmdbError(const CallbackInfo& info);
//NAN_METHOD(getBufferForAddress);
napi_value createBufferForAddress(napi_env env, napi_callback_info info);
napi_value getViewAddress(napi_env env, napi_callback_info info);
napi_value detachBuffer(napi_env env, napi_callback_info info);
Value getAddress(const CallbackInfo& info);
Expand Down
12 changes: 11 additions & 1 deletion src/misc.cpp
Expand Up @@ -24,8 +24,8 @@ void setupExportMisc(Napi::Env env, Object exports) {
exports.Set("version", versionObj);
exports.Set("setGlobalBuffer", Function::New(env, setGlobalBuffer));
exports.Set("lmdbError", Function::New(env, lmdbError));
//exports.Set("getBufferForAddress", Function::New(env, getBufferForAddress));
exports.Set("enableDirectV8", Function::New(env, enableDirectV8));
EXPORT_NAPI_FUNCTION("createBufferForAddress", createBufferForAddress);
EXPORT_NAPI_FUNCTION("getAddress", getViewAddress);
EXPORT_NAPI_FUNCTION("detachBuffer", detachBuffer);
}
Expand Down Expand Up @@ -134,6 +134,16 @@ Value setGlobalBuffer(const CallbackInfo& info) {
auto array_buffer = v8::ArrayBuffer::New(Isolate::GetCurrent(), std::move(backing));
info.GetReturnValue().Set(array_buffer);
}*/
NAPI_FUNCTION(createBufferForAddress) {
ARGS(2)
void* data;
GET_INT64_ARG(data, 0);
size_t length;
GET_INT64_ARG(length, 1);
napi_create_external_buffer(env, length, data, nullptr, nullptr, &returnValue);
return returnValue;
}

NAPI_FUNCTION(getViewAddress) {
ARGS(1)
void* data;
Expand Down
3 changes: 3 additions & 0 deletions test/index.test.js
Expand Up @@ -13,6 +13,7 @@ import inspector from 'inspector'
let nativeMethods, dirName = dirname(fileURLToPath(import.meta.url))

import { open, levelup, bufferToKeyValue, keyValueToBuffer, asBinary, ABORT, IF_EXISTS } from '../index.js';
import { createBufferForAddress } from '../native.js'
import { RangeIterable } from '../util/RangeIterable.js'
import { assert } from 'console';
import { openAsClass } from '../open.js';
Expand Down Expand Up @@ -97,6 +98,8 @@ describe('lmdb-js', function() {
it('zero length values', async function() {
await db.committed // should be able to await db even if nothing has happened
db.put(5, asBinary(Buffer.from([])));
db.put(5, asBinary(createBufferForAddress(16, 0)));// externally allocated buffers of zero-length with the same non-null-pointer can crash node, #161
db.put(5, asBinary(createBufferForAddress(16, 0)));
await db2.put('key1', asBinary(Buffer.from([])));
should.equal(db.getBinary(5).length, 0);
should.equal(db2.getBinary('key1').length, 0);
Expand Down
3 changes: 2 additions & 1 deletion write.js
Expand Up @@ -175,7 +175,8 @@ export function addWriteMethods(LMDBStore, { env, fixedBuffer, resetReadTxn, use
let valueArrayBuffer = valueBuffer.buffer;
// record pointer to value buffer
float64[position] = (valueArrayBuffer.address ||
(valueArrayBuffer.address = (getAddress(valueBuffer) - valueBuffer.byteOffset)))
(valueBuffer.length === 0 ? 0 : // externally allocated buffers of zero-length with the same non-null-pointer can crash node, #161
(valueArrayBuffer.address = (getAddress(valueBuffer) - valueBuffer.byteOffset))))
+ valueBuffer.byteOffset;
mustCompress = valueBuffer[0] >= 250; // this is the compression indicator, so we must compress
}
Expand Down

0 comments on commit 1e0335e

Please sign in to comment.