Skip to content

Commit 7b3f710

Browse files
committed
Python: Model aiosqlite
1 parent 9975fac commit 7b3f710

File tree

7 files changed

+73
-1
lines changed

7 files changed

+73
-1
lines changed

docs/codeql/reusables/supported-frameworks.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ and the CodeQL library pack ``codeql/python-all`` (`changelog <https://github.co
223223
aioch, Database
224224
aiomysql, Database
225225
aiopg, Database
226+
aiosqlite, Database
226227
asyncpg, Database
227228
cassandra-driver, Database
228229
clickhouse-driver, Database

python/ql/lib/semmle/python/Frameworks.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
private import semmle.python.frameworks.Aioch
88
private import semmle.python.frameworks.Aiohttp
99
private import semmle.python.frameworks.Aiomysql
10+
private import semmle.python.frameworks.Aiosqlite
1011
private import semmle.python.frameworks.Aiopg
1112
private import semmle.python.frameworks.Asyncpg
1213
private import semmle.python.frameworks.CassandraDriver
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/**
2+
* Provides classes modeling security-relevant aspects of the `aiosqlite` PyPI package.
3+
* See
4+
* - https://pypi.org/project/aiosqlite/
5+
*/
6+
7+
private import python
8+
private import semmle.python.dataflow.new.DataFlow
9+
private import semmle.python.Concepts
10+
private import semmle.python.ApiGraphs
11+
private import semmle.python.frameworks.PEP249
12+
13+
/** Provides models for the `aiosqlite` PyPI package. */
14+
private module Aiosqlite {
15+
/**
16+
* A model of `aiosqlite` as a module that implements PEP 249 using asyncio, providing
17+
* ways to execute SQL statements against a database.
18+
*/
19+
class AiosqlitePEP249 extends PEP249::AsyncPEP249ModuleApiNode {
20+
AiosqlitePEP249() { this = API::moduleImport("aiosqlite") }
21+
}
22+
23+
/**
24+
* An additional cursor, that is return from the coroutine Connection.execute,
25+
* see https://aiosqlite.omnilib.dev/en/latest/api.html#aiosqlite.Connection.execute
26+
*/
27+
class AiosqliteCursor extends PEP249::AsyncDatabaseCursor {
28+
AiosqliteCursor() {
29+
this =
30+
API::moduleImport("aiosqlite")
31+
.getMember("connect")
32+
.getReturn()
33+
.getAwaited()
34+
.getMember("execute")
35+
.getReturn()
36+
.getAwaited()
37+
}
38+
}
39+
}

python/ql/lib/semmle/python/frameworks/PEP249.qll

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@ module PEP249 {
5252
result in ["sql", "statement", "operation", "query", "query_string", "sql_script"]
5353
}
5454

55-
private string getExecuteMethodName() { result in ["execute", "executemany", "executescript"] }
55+
private string getExecuteMethodName() {
56+
result in ["execute", "executemany", "executescript", "execute_insert", "execute_fetchall"]
57+
}
5658

5759
/**
5860
* A call to an execute method on a database cursor or a connection, such as `execute`

python/ql/test/library-tests/frameworks/aiosqlite/ConceptsTest.expected

Whitespace-only changes.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import python
2+
import experimental.meta.ConceptsTest
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import aiosqlite
2+
3+
# see https://pypi.org/project/aiosqlite/
4+
5+
async def test():
6+
db = await aiosqlite.connect(...)
7+
8+
await db.execute("sql") # $ getSql="sql" constructedSql="sql"
9+
await db.execute(sql="sql") # $ getSql="sql" constructedSql="sql"
10+
11+
cursor = await db.cursor()
12+
cursor.execute("sql") # $ constructedSql="sql"
13+
14+
cursor = await db.execute("sql") # $ getSql="sql" constructedSql="sql"
15+
cursor.execute("sql") # $ constructedSql="sql"
16+
17+
async with aiosqlite.connect(...) as db:
18+
db.row_factory = aiosqlite.Row
19+
async with db.execute("sql") as cursor: # $ getSql="sql" constructedSql="sql"
20+
async for row in cursor:
21+
print(row['column'])
22+
23+
# nonstandard
24+
await db.execute_insert("sql") # $ getSql="sql" constructedSql="sql"
25+
await db.execute_fetchall("sql") # $ getSql="sql" constructedSql="sql"
26+
await db.executescript("sql") # $ getSql="sql" constructedSql="sql"
27+
await db.executescript(sql_script="sql") # $ getSql="sql" constructedSql="sql"

0 commit comments

Comments
 (0)