Skip to content

Commit a854fb8

Browse files
committed
Add documentation and refactor code
1 parent f1e71e2 commit a854fb8

File tree

1 file changed

+37
-10
lines changed

1 file changed

+37
-10
lines changed

python/ql/src/experimental/semmle/python/frameworks/SqlAlchemy.qll

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,14 @@ private import python
77
private import semmle.python.dataflow.new.DataFlow
88
private import semmle.python.dataflow.new.TaintTracking
99
private import semmle.python.ApiGraphs
10-
10+
private import semmle.python.Concepts
1111

1212
private module SqlAlchemy {
13+
/**
14+
* An instantization of a SqlAlchemy Session object.
15+
* See https://docs.sqlalchemy.org/en/14/orm/session_api.html#sqlalchemy.orm.Session and
16+
* https://docs.sqlalchemy.org/en/14/orm/session_api.html#sqlalchemy.orm.sessionmaker
17+
*/
1318
private class SqlAlchemySessionInstance extends API::Node {
1419
SqlAlchemySessionInstance() {
1520
this in [
@@ -18,26 +23,40 @@ private module SqlAlchemy {
1823
]
1924
}
2025

21-
override string toString() { result = "Use of SqlAlchemy Session instance method" }
26+
override string toString() { result = "Use of SqlAlchemy Session instantization" }
2227
}
2328

29+
/**
30+
* An instantization of a SqlAlchemy Engine object.
31+
* See https://docs.sqlalchemy.org/en/14/core/engines.html#sqlalchemy.create_engine
32+
*/
2433
private class SqlAlchemyEngineInstance extends API::Node {
2534
SqlAlchemyEngineInstance() {
2635
this = API::moduleImport("sqlalchemy").getMember("create_engine").getReturn()
2736
}
2837

29-
override string toString() { result = "Use of SqlAlchemy Engine instance method" }
38+
override string toString() { result = "Use of SqlAlchemy create_engine member" }
3039
}
3140

41+
/**
42+
* An instantization of a SqlAlchemy Query object.
43+
* See https://docs.sqlalchemy.org/en/14/orm/query.html?highlight=query#sqlalchemy.orm.Query
44+
*/
3245
private class SqlAlchemyQueryInstance extends API::Node {
3346
SqlAlchemyQueryInstance() {
34-
this instanceof SqlAlchemySessionInstance and
35-
this = this.getMember("query").getReturn()
47+
this = any(SqlAlchemySessionInstance sessionInstance).getMember("query").getReturn()
3648
}
3749

38-
override string toString() { result = "Use of SqlAlchemy Query instance method" }
50+
override string toString() { result = "Use of SqlAlchemy Session Query member" }
3951
}
4052

53+
/**
54+
* A call to `execute` meant to execute an SQL expression
55+
* See the following links:
56+
* - https://docs.sqlalchemy.org/en/14/core/connections.html?highlight=execute#sqlalchemy.engine.Connection.execute
57+
* - https://docs.sqlalchemy.org/en/14/core/connections.html?highlight=execute#sqlalchemy.engine.Engine.execute
58+
* - https://docs.sqlalchemy.org/en/14/orm/session_api.html?highlight=execute#sqlalchemy.orm.Session.execute
59+
*/
4160
private class SqlAlchemyExecuteCall extends DataFlow::CallCfgNode, SqlExecution::Range {
4261
SqlAlchemyExecuteCall() {
4362
exists(SqlAlchemySessionInstance sessionInstance, SqlAlchemyEngineInstance engineInstance |
@@ -50,19 +69,27 @@ private module SqlAlchemy {
5069
override DataFlow::Node getSql() { result = this.getArg(0) }
5170
}
5271

72+
/**
73+
* A call to `scalar` meant to execute an SQL expression
74+
* See https://docs.sqlalchemy.org/en/14/orm/session_api.html#sqlalchemy.orm.Session.scalar and
75+
* https://docs.sqlalchemy.org/en/14/core/connections.html?highlight=scalar#sqlalchemy.engine.Engine.scalar
76+
*/
5377
private class SqlAlchemyScalarCall extends DataFlow::CallCfgNode, SqlExecution::Range {
5478
SqlAlchemyScalarCall() {
55-
exists(SqlAlchemySessionInstance sessionInstance |
56-
this = sessionInstance.getMember("scalar").getACall()
57-
)
79+
this = any(SqlAlchemySessionInstance sessionInstance).getMember("scalar").getACall() or
80+
this = any(SqlAlchemyEngineInstance engineInstance).getMember("scalar").getACall()
5881
}
5982

6083
override DataFlow::Node getSql() { result = this.getArg(0) }
6184
}
6285

86+
/**
87+
* A call on a Query object
88+
* See https://docs.sqlalchemy.org/en/14/orm/query.html?highlight=query#sqlalchemy.orm.Query
89+
*/
6390
private class SqlAlchemyQueryCall extends DataFlow::CallCfgNode, SqlExecution::Range {
6491
SqlAlchemyQueryCall() {
65-
exists(SqlAlchemyQueryInstance queryInstance | this = queryInstance.getAMember().getACall())
92+
this = any(SqlAlchemyQueryInstance queryInstance).getAMember().getACall()
6693
}
6794

6895
override DataFlow::Node getSql() { result = this.getArg(0) }

0 commit comments

Comments
 (0)