sqlite: prevent reentrant session.close() · nodejs/node@e2f952f · GitHub
Skip to content

Commit e2f952f

Browse files
trivikraduh95
authored andcommitted
sqlite: prevent reentrant session.close()
Reject session.close() while generating a changeset or patchset. Closing the session at that point frees it while SQLite is still using it, causing a use-after-free. Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com> Assisted-by: codex:gpt-5.6-sol PR-URL: #65349 Fixes: #65347 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
1 parent 810929b commit e2f952f

4 files changed

Lines changed: 31 additions & 1 deletion

File tree

doc/api/sqlite.md

Lines changed: 2 additions & 1 deletion

src/node_sqlite.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4299,6 +4299,10 @@ void Session::Changeset(const FunctionCallbackInfo<Value>& args) {
42994299
env, session->session_ == nullptr, "session is not open");
43004300
THROW_AND_RETURN_IF_IN_AUTHORIZER(env, session->database_.get());
43014301

4302+
session->is_generating_changeset_ = true;
4303+
auto changeset_guard =
4304+
OnScopeLeave([&] { session->is_generating_changeset_ = false; });
4305+
43024306
int nChangeset;
43034307
void* pChangeset;
43044308
int r = sqliteChangesetFunc(session->session_, &nChangeset, &pChangeset);
@@ -4324,6 +4328,8 @@ void Session::Close(const FunctionCallbackInfo<Value>& args) {
43244328
env, !session->database_->IsOpen(), "database is not open");
43254329
THROW_AND_RETURN_ON_BAD_STATE(
43264330
env, session->session_ == nullptr, "session is not open");
4331+
THROW_AND_RETURN_ON_BAD_STATE(
4332+
env, session->is_generating_changeset_, "session is currently in use");
43274333

43284334
session->Delete();
43294335
}

src/node_sqlite.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,7 @@ class Session : public BaseObject {
458458
void Delete();
459459
sqlite3_session* session_;
460460
BaseObjectPtr<DatabaseSync> database_; // The Parent Database
461+
bool is_generating_changeset_ = false;
461462

462463
friend class DatabaseSync;
463464
};

test/parallel/test-sqlite-session.js

Lines changed: 22 additions & 0 deletions

0 commit comments

Comments
 (0)