Skip to content

Commit 4571b31

Browse files
committed
Python: Fix false negative
1 parent 03c62fd commit 4571b31

File tree

2 files changed

+22
-6
lines changed

2 files changed

+22
-6
lines changed

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

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,22 @@ private module Django {
275275
* Gets a reference to the `django.db.models.expressions.RawSQL` class.
276276
*/
277277
DataFlow::Node classRef() { result = classRef(DataFlow::TypeTracker::end()) }
278+
279+
/** Gets an instance of the `django.db.models.expressions.RawSQL` class. */
280+
private DataFlow::Node classInstance(DataFlow::TypeTracker t, ControlFlowNode sql) {
281+
t.start() and
282+
exists(CallNode c | result.asCfgNode() = c |
283+
c.getFunction() = classRef().asCfgNode() and
284+
c.getArg(0) = sql
285+
)
286+
or
287+
exists(DataFlow::TypeTracker t2 | result = classInstance(t2, sql).track(t2, t))
288+
}
289+
290+
/** Gets an instance of the `django.db.models.expressions.RawSQL` class. */
291+
DataFlow::Node classInstance(ControlFlowNode sql) {
292+
result = classInstance(DataFlow::TypeTracker::end(), sql)
293+
}
278294
}
279295
}
280296
}
@@ -305,15 +321,15 @@ private module Django {
305321
*/
306322
private class ObjectsAnnotate extends SqlExecution::Range, DataFlow::CfgNode {
307323
override CallNode node;
308-
CallNode raw;
324+
ControlFlowNode sql;
309325

310326
ObjectsAnnotate() {
311327
node.getFunction() = django::db::models::objects_attr("annotate").asCfgNode() and
312-
raw in [node.getArg(_), node.getArgByName(_)] and
313-
raw.getFunction() = django::db::models::expressions::RawSQL::classRef().asCfgNode()
328+
django::db::models::expressions::RawSQL::classInstance(sql).asCfgNode() in [node.getArg(_),
329+
node.getArgByName(_)]
314330
}
315331

316-
override DataFlow::Node getSql() { result.asCfgNode() = raw.getArg(0) }
332+
override DataFlow::Node getSql() { result.asCfgNode() = sql }
317333
}
318334

319335
/**

python/ql/test/experimental/library-tests/frameworks/django/SqlExecution.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,5 @@ def test_model():
2424
User.objects.extra("some sql") # $getSql="some sql"
2525
User.objects.extra(select="select", where="where", tables="tables", order_by="order_by") # $getSql="select" $getSql="where" $getSql="tables" $getSql="order_by"
2626

27-
raw = RawSQL("so raw")
28-
User.objects.annotate(val=raw) # $f-:getSql="so raw"
27+
raw = RawSQL("so raw") # $getSql="so raw"
28+
User.objects.annotate(val=raw)

0 commit comments

Comments
 (0)