Skip to content

Commit 90dbb60

Browse files
authored
Merge pull request #4819 from RasmusWL/pep249-execute-on-connection
Approved by yoff
2 parents 66f4120 + 8d8e92e commit 90dbb60

File tree

2 files changed

+20
-11
lines changed
  • python/ql
    • src/semmle/python/frameworks
    • test/experimental/library-tests/frameworks/stdlib

2 files changed

+20
-11
lines changed

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

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -62,54 +62,63 @@ module Connection {
6262
}
6363

6464
/**
65-
* Provides models for the `db.Connection.cursor` method.
65+
* Provides models for the `cursor` method on a connection.
6666
* See https://www.python.org/dev/peps/pep-0249/#cursor.
6767
*/
6868
module cursor {
69-
/** Gets a reference to the `db.connection.cursor` method. */
69+
/** Gets a reference to the `cursor` method on a connection. */
7070
private DataFlow::Node methodRef(DataFlow::TypeTracker t) {
7171
t.startInAttr("cursor") and
7272
result = Connection::instance()
7373
or
7474
exists(DataFlow::TypeTracker t2 | result = methodRef(t2).track(t2, t))
7575
}
7676

77-
/** Gets a reference to the `db.connection.cursor` metod. */
77+
/** Gets a reference to the `cursor` method on a connection. */
7878
DataFlow::Node methodRef() { result = methodRef(DataFlow::TypeTracker::end()) }
7979

80-
/** Gets a reference to a result of calling `db.connection.cursor`. */
80+
/** Gets a reference to a result of calling the `cursor` method on a connection. */
8181
private DataFlow::Node methodResult(DataFlow::TypeTracker t) {
8282
t.start() and
8383
result.asCfgNode().(CallNode).getFunction() = methodRef().asCfgNode()
8484
or
8585
exists(DataFlow::TypeTracker t2 | result = methodResult(t2).track(t2, t))
8686
}
8787

88-
/** Gets a reference to a result of calling `db.connection.cursor`. */
88+
/** Gets a reference to a result of calling the `cursor` method on a connection. */
8989
DataFlow::Node methodResult() { result = methodResult(DataFlow::TypeTracker::end()) }
9090
}
9191

9292
/**
93-
* Gets a reference to the `db.Connection.Cursor.execute` function.
93+
* Gets a reference to the `execute` method on a cursor (or on a connection).
94+
*
95+
* Note: while `execute` method on a connection is not part of PEP249, if it is used, we
96+
* recognize it as an alias for constructing a cursor and calling `execute` on it.
97+
*
9498
* See https://www.python.org/dev/peps/pep-0249/#id15.
9599
*/
96100
private DataFlow::Node execute(DataFlow::TypeTracker t) {
97101
t.startInAttr("execute") and
98-
result = cursor::methodResult()
102+
result in [cursor::methodResult(), Connection::instance()]
99103
or
100104
exists(DataFlow::TypeTracker t2 | result = execute(t2).track(t2, t))
101105
}
102106

103107
/**
104-
* Gets a reference to the `db.Connection.Cursor.execute` function.
108+
* Gets a reference to the `execute` method on a cursor (or on a connection).
109+
*
110+
* Note: while `execute` method on a connection is not part of PEP249, if it is used, we
111+
* recognize it as an alias for constructing a cursor and calling `execute` on it.
112+
*
105113
* See https://www.python.org/dev/peps/pep-0249/#id15.
106114
*/
107115
DataFlow::Node execute() { result = execute(DataFlow::TypeTracker::end()) }
108116

109-
private class DbConnectionExecute extends SqlExecution::Range, DataFlow::CfgNode {
117+
/** A call to the `execute` method on a cursor (or on a connection). */
118+
private class ExecuteCall extends SqlExecution::Range, DataFlow::CfgNode {
110119
override CallNode node;
111120

112-
DbConnectionExecute() { node.getFunction() = execute().asCfgNode() }
121+
ExecuteCall() { node.getFunction() = execute().asCfgNode() }
113122

114123
override DataFlow::Node getSql() {
115124
result.asCfgNode() in [node.getArg(0), node.getArgByName("sql")]

python/ql/test/experimental/library-tests/frameworks/stdlib/pep249.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
db = sqlite3.connect("example.db")
33

44
# non standard
5-
db.execute("some sql", (42,)) # $ MISSING: getSql="some sql"
5+
db.execute("some sql", (42,)) # $ getSql="some sql"
66

77
cursor = db.cursor()
88
cursor.execute("some sql", (42,)) # $ getSql="some sql"

0 commit comments

Comments
 (0)