Skip to content

Commit b0c5457

Browse files
author
Daniele Briggi
committed
Merge branch '#122-implement-server-side-prepared-statement' of https://github.com/sqlitecloud/sqlitecloud-js into #122-implement-server-side-prepared-statement
2 parents 0da5e9e + dd7b1eb commit b0c5457

File tree

5 files changed

+37
-19
lines changed

5 files changed

+37
-19
lines changed

src/drivers/protocol.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ export function popData(buffer: Buffer): { data: SQLiteCloudDataTypes | SQLiteCl
338338
export function formatCommand(command: SQLiteCloudCommand): string {
339339
if (command.parameters && command.parameters.length > 0) {
340340
// by SCSP the string paramenters in the array are zero-terminated
341-
return serializeCommand([command.query, ...command.parameters || []], true)
341+
return serializeCommand([command.query, ...(command.parameters || [])], true)
342342
}
343343
return serializeData(command.query, false)
344344
}

src/drivers/statement.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,10 @@ export class Statement<T> {
3333
* Binds parameters to the prepared statement and calls the callback when done
3434
* or when an error occurs. The function returns the Statement object to allow
3535
* for function chaining. The first and only argument to the callback is null
36-
* when binding was successful. Binding parameters with this function completely
37-
* resets the statement object and row cursor and removes all previously bound
36+
* when binding was successful. Binding parameters with this function completely
37+
* resets the statement object and row cursor and removes all previously bound
3838
* parameters, if any.
39-
*
39+
*
4040
* In SQLiteCloud the statement is prepared on the database server and binding errors
4141
* are raised on execution time.
4242
*/

src/drivers/utilities.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ export function sanitizeSQLiteIdentifier(identifier: any): string {
9696
}
9797

9898
// escape double quotes
99-
const escaped = trimmed.replace(/"/g, '\"')
99+
const escaped = trimmed.replace(/"/g, '""')
100100

101101
// Wrap in double quotes for safety
102102
return `"${escaped}"`

test/database.test.ts

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -476,35 +476,53 @@ describe('Database.sql (async)', () => {
476476
}
477477
})
478478

479-
it('should sanitize SQL Injection as table name', async () => {
480-
const database = await getTestingDatabaseAsync()
481-
482-
const databaseName = sanitizeSQLiteIdentifier('people.sqlite; SELECT * FROM people; -- ')
483-
await expect(database.sql(`USE DATABASE ${databaseName}`)).rejects.toThrow('Database name contains invalid characters (people.sqlite; SELECT * FROM people; --).')
484-
485-
const table = sanitizeSQLiteIdentifier('people; -- ')
486-
await expect(database.sql(`SELECT * FROM ${table} WHERE people = 1`)).rejects.toThrow('no such table: people; --')
479+
describe('should sanitize identifiers', () => {
480+
it('should sanitize database name and run the query', async () => {
481+
const database = await getTestingDatabaseAsync()
482+
483+
const databaseName = sanitizeSQLiteIdentifier('people.sqlite')
484+
await expect(database.sql(`USE DATABASE ${databaseName}`)).resolves.toBe('OK')
485+
})
486+
487+
it('should sanitize table name and run the query', async () => {
488+
const database = await getTestingDatabaseAsync()
489+
490+
const table = sanitizeSQLiteIdentifier('people')
491+
await expect(database.sql(`USE DATABASE people.sqlite; SELECT id FROM ${table} LIMIT 1`)).resolves.toMatchObject([{ id: 1 }])
492+
})
493+
494+
it('should sanitize SQL Injection as table name', async () => {
495+
const database = await getTestingDatabaseAsync()
496+
497+
const databaseName = sanitizeSQLiteIdentifier('people.sqlite; SELECT * FROM people; -- ')
498+
await expect(database.sql(`USE DATABASE ${databaseName}`)).rejects.toThrow(
499+
'Database name contains invalid characters (people.sqlite; SELECT * FROM people; --).'
500+
)
501+
502+
const table = sanitizeSQLiteIdentifier('people; -- ')
503+
await expect(database.sql(`SELECT * FROM ${table} WHERE people = 1`)).rejects.toThrow('no such table: people; --')
504+
})
487505
})
488506

489507
it('should throw exception when using table name as binding', async () => {
490-
const database = await getTestingDatabaseAsync()
508+
const database = await getTestingDatabaseAsync()
491509
const table = 'people'
492510
await expect(database.sql`USE DATABASE people.sqlite; SELECT * FROM ${table}`).rejects.toThrow('near "?": syntax error')
493511
})
494512

495513
it('should built in commands accept bindings', async () => {
496514
const database = await getTestingDatabaseAsync()
497-
515+
498516
let databaseName = 'people.sqlite'
499517
await expect(database.sql`USE DATABASE ${databaseName}`).resolves.toBe('OK')
500-
518+
501519
databaseName = 'people.sqlite; SELECT * FROM people'
502520
await expect(database.sql`USE DATABASE ${databaseName}`).rejects.toThrow('Database name contains invalid characters (people.sqlite; SELECT * FROM people).')
503-
521+
504522
let key = 'logo_level'
505523
let value = 'debug'
506524
await expect(database.sql`SET KEY ${key} TO ${value}`).resolves.toBe('OK')
507-
525+
508526
key = 'logo_level'
509527
value = 'debug; DROP TABLE people'
510528
await expect(database.sql`SET KEY ${key} TO ${value}`).resolves.toBe('OK')

test/utilities.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,6 @@ describe('sanitizeSQLiteIdentifier()', () => {
163163
it('should double quotes for sql injection', () => {
164164
const identifier = ' chinook.sql; DROP TABLE "albums" '
165165
const sanitized = sanitizeSQLiteIdentifier(identifier)
166-
expect(sanitized).toBe('"chinook.sql; DROP TABLE \"albums\""')
166+
expect(sanitized).toBe('"chinook.sql; DROP TABLE \"\"albums\"\""')
167167
})
168168
})

0 commit comments

Comments
 (0)