sqlite: fix crash session extension callbacks with workers · nodejs/node@3eeb7b4
@@ -1668,26 +1668,28 @@ void Backup(const FunctionCallbackInfo<Value>& args) {
16681668 job->ScheduleBackup();
16691669}
167016701671+struct ConflictCallbackContext {
1672+ std::function<bool(std::string_view)> filterCallback;
1673+ std::function<int(int)> conflictCallback;
1674+};
1675+16711676// the reason for using static functions here is that SQLite needs a
16721677// function pointer
1673-static std::function<int(int)> conflictCallback;
1674167816751679static int xConflict(void* pCtx, int eConflict, sqlite3_changeset_iter* pIter) {
1676-if (!conflictCallback) return SQLITE_CHANGESET_ABORT;
1677-return conflictCallback(eConflict);
1680+auto ctx = static_cast<ConflictCallbackContext*>(pCtx);
1681+if (!ctx->conflictCallback) return SQLITE_CHANGESET_ABORT;
1682+return ctx->conflictCallback(eConflict);
16781683}
167916841680-static std::function<bool(std::string)> filterCallback;
1681-16821685static int xFilter(void* pCtx, const char* zTab) {
1683-if (!filterCallback) return 1;
1684-1685-return filterCallback(zTab) ? 1 : 0;
1686+auto ctx = static_cast<ConflictCallbackContext*>(pCtx);
1687+ if (!ctx->filterCallback) return 1;
1688+return ctx->filterCallback(zTab) ? 1 : 0;
16861689}
1687169016881691void DatabaseSync::ApplyChangeset(const FunctionCallbackInfo<Value>& args) {
1689- conflictCallback = nullptr;
1690- filterCallback = nullptr;
1692+ ConflictCallbackContext context;
1691169316921694 DatabaseSync* db;
16931695ASSIGN_OR_RETURN_UNWRAP(&db, args.This());
@@ -1723,7 +1725,7 @@ void DatabaseSync::ApplyChangeset(const FunctionCallbackInfo<Value>& args) {
17231725return;
17241726 }
17251727 Local<Function> conflictFunc = conflictValue.As<Function>();
1726- conflictCallback = [env, conflictFunc](int conflictType) -> int {
1728+context.conflictCallback = [env, conflictFunc](int conflictType) -> int {
17271729 Local<Value> argv[] = {Integer::New(env->isolate(), conflictType)};
17281730 TryCatch try_catch(env->isolate());
17291731 Local<Value> result =
@@ -1761,15 +1763,18 @@ void DatabaseSync::ApplyChangeset(const FunctionCallbackInfo<Value>& args) {
1761176317621764 Local<Function> filterFunc = filterValue.As<Function>();
176317651764- filterCallback = [env, filterFunc](std::string item) -> bool {
1766+ context.filterCallback = [env,
1767+ filterFunc](std::string_view item) -> bool {
17651768// TODO(@jasnell): The use of ToLocalChecked here means that if
17661769// the filter function throws an error the process will crash.
17671770// The filterCallback should be updated to avoid the check and
17681771// propagate the error correctly.
1769- Local<Value> argv[] = {String::NewFromUtf8(env->isolate(),
1770- item.c_str(),
1771- NewStringType::kNormal)
1772- .ToLocalChecked()};
1772+ Local<Value> argv[] = {
1773+String::NewFromUtf8(env->isolate(),
1774+ item.data(),
1775+ NewStringType::kNormal,
1776+static_cast<int>(item.size()))
1777+ .ToLocalChecked()};
17731778 Local<Value> result =
17741779 filterFunc->Call(env->context(), Null(env->isolate()), 1, argv)
17751780 .ToLocalChecked();
@@ -1785,7 +1790,7 @@ void DatabaseSync::ApplyChangeset(const FunctionCallbackInfo<Value>& args) {
17851790const_cast<void*>(static_cast<const void*>(buf.data())),
17861791 xFilter,
17871792 xConflict,
1788-nullptr);
1793+static_cast<void*>(&context));
17891794if (r == SQLITE_OK) {
17901795 args.GetReturnValue().Set(true);
17911796return;