Skip to content

sqlite: authorizer can finalize another active statement and change outer statement outcome #65368

Description

@trivikr

Version

main

Platform

N/A

Subsystem

sqlite

What steps will reproduce the bug?

import { DatabaseSync, constants } from 'node:sqlite';

const db = new DatabaseSync(':memory:');
db.exec('CREATE TABLE t(x); INSERT INTO t VALUES (1), (2), (3)');

const victim = db.prepare('SELECT x FROM t');
victim.iterate().next(); // Leave its VM active.

db.setAuthorizer((action) => {
  if (action === constants.SQLITE_DROP_TABLE)
    victim.close();
  return constants.SQLITE_OK;
});

db.exec('DROP TABLE t');
console.log('DROP TABLE succeeded');

How often does it reproduce? Is there a required condition?

Always

What is the expected behavior? Why is that the expected behavior?

Finalizing another active statement from within the authorizer callback should be rejected or deferred. The active SELECT should continue holding its lock, causing DROP TABLE to fail with ERR_SQLITE_ERROR: database table is locked.

What do you see instead?

The script prints DROP TABLE succeeded. During authorization, the callback finalizes the active SELECT, releases its table lock, and allows the outer DROP TABLE to succeed.

Additional information

No response

Metadata

Metadata

Assignees

Labels

sqliteIssues and PRs related to the SQLite subsystem.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions