Skip to content

Commit 73863bf

Browse files
committed
fix(sqlite_impl): always copy changeset before applying
SQLite reaches JavaScript through a user-defined SQL function in a CHECK constraint or trigger, not just through an explicit filter or onConflict callback, so the previous condition left the input buffer detachable while SQLite was still reading it. Ports nodejs/node#65870.
1 parent d85d924 commit 73863bf

1 file changed

Lines changed: 6 additions & 5 deletions

File tree

‎src/sqlite_impl.cpp‎

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2491,12 +2491,13 @@ Napi::Value DatabaseSync::ApplyChangeset(const Napi::CallbackInfo &info) {
24912491
return env.Undefined();
24922492
}
24932493

2494-
// A filter or conflict callback may detach or overwrite the input buffer
2495-
// mid-apply, so SQLite has to read a private copy. With no callbacks, no
2496-
// JavaScript runs during sqlite3changeset_apply(), so no copy is needed.
2494+
// SQLite can invoke JavaScript through a filter or conflict callback, and
2495+
// also through a user-defined SQL function reached from a CHECK constraint
2496+
// or trigger, so JavaScript can run even with no callbacks supplied. Give
2497+
// SQLite a private copy it cannot detach or overwrite mid-apply. Ports
2498+
// https://github.com/nodejs/node/pull/65870.
24972499
std::vector<uint8_t> changeset_copy;
2498-
if (byte_length > 0 &&
2499-
(callbacks.filterCallback || callbacks.conflictCallback)) {
2500+
if (byte_length > 0) {
25002501
changeset_copy.assign(data, data + byte_length);
25012502
data = changeset_copy.data();
25022503
}

0 commit comments

Comments
 (0)