GeezerVison is showing github.com — sqlite: reject statement-less SQL in SQLTagStore · nodejs/node@043dfe4
File tree
Expand file treeCollapse file tree
Open diff view settings
Expand file treeCollapse file tree
Open diff view settings
Collapse file
Copy file name to clipboardExpand all lines: src/node_sqlite.cc +8Lines changed: 8 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -3619,6 +3619,14 @@ BaseObjectPtr<StatementSync> SQLTagStore::PrepareStatement( |
3619 | 3619 | return BaseObjectPtr<StatementSync>(); |
3620 | 3620 | } |
3621 | 3621 |
|
| 3622 | + // sqlite3_prepare_v2() reports success without producing a statement when |
| 3623 | + // the input holds no SQL, such as a comment. Such a statement cannot be |
| 3624 | + // bound or executed, so reject it instead of caching it. |
| 3625 | + if (s == nullptr) { |
| 3626 | + THROW_ERR_INVALID_ARG_VALUE(env, "The SQL query contains no statements."); |
| 3627 | + return BaseObjectPtr<StatementSync>(); |
| 3628 | + } |
| 3629 | + |
3622 | 3630 | BaseObjectPtr<StatementSync> stmt_obj = StatementSync::Create( |
3623 | 3631 | env, BaseObjectPtr<DatabaseSync>(session->database_), s); |
3624 | 3632 |
|
|
Collapse file
Copy file name to clipboardExpand all lines: test/parallel/test-sqlite-template-tag.js +23Lines changed: 23 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -317,6 +317,29 @@ test('sql error messages are descriptive', () => { |
317 | 317 | }); |
318 | 318 | }); |
319 | 319 |
|
| 320 | +test('rejects SQL that contains no statements', () => { |
| 321 | + const expectedError = { |
| 322 | + code: 'ERR_INVALID_ARG_VALUE', |
| 323 | + message: /contains no statements/, |
| 324 | + }; |
| 325 | + |
| 326 | + for (const method of ['run', 'get', 'all', 'iterate']) { |
| 327 | + assert.throws(() => { |
| 328 | + // eslint-disable-next-line no-unused-expressions |
| 329 | + sql[method]`-- comment`; |
| 330 | + }, expectedError); |
| 331 | + |
| 332 | + assert.throws(() => { |
| 333 | + // eslint-disable-next-line no-unused-expressions |
| 334 | + sql[method]``; |
| 335 | + }, expectedError); |
| 336 | + } |
| 337 | + |
| 338 | + // A rejected statement must not be cached, so a later valid query with the |
| 339 | + // same tag store still works. |
| 340 | + assert.strictEqual(sql.run`INSERT INTO foo (text) VALUES (${'bob'})`.changes, 1); |
| 341 | +}); |
| 342 | + |
320 | 343 | test('a tag store keeps the database alive by itself', () => { |
321 | 344 | const sql = new DatabaseSync(':memory:').createTagStore(); |
322 | 345 |
|
|