Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 383d846

Browse files
committed
Python: address review
- smooth out future merge - keyword argument for execute
1 parent e1dfbc0 commit 383d846

2 files changed

Lines changed: 50 additions & 13 deletions

File tree

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

Lines changed: 49 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,12 @@ private import experimental.semmle.python.Concepts
99

1010
/**
1111
* Provides models for the `django` PyPI package.
12-
* See https://django.palletsprojects.com/en/1.1.x/.
12+
* See https://www.djangoproject.com/.
1313
*/
1414
private module Django {
15+
// ---------------------------------------------------------------------------
16+
// django
17+
// ---------------------------------------------------------------------------
1518
/** Gets a reference to the `django` module. */
1619
private DataFlow::Node django(DataFlow::TypeTracker t) {
1720
t.start() and
@@ -23,21 +26,52 @@ private module Django {
2326
/** Gets a reference to the `django` module. */
2427
DataFlow::Node django() { result = django(DataFlow::TypeTracker::end()) }
2528

26-
/** Provides models for the `django` module. */
27-
module django {
28-
/** Gets a reference to the `django.db` module. */
29-
private DataFlow::Node db(DataFlow::TypeTracker t) {
29+
/**
30+
* Gets a reference to the attribute `attr_name` of the `django` module.
31+
* WARNING: Only holds for a few predefined attributes.
32+
*/
33+
private DataFlow::Node django_attr(DataFlow::TypeTracker t, string attr_name) {
34+
attr_name in ["db"] and
35+
(
3036
t.start() and
31-
result = DataFlow::importNode("django.db")
32-
or
33-
t.startInAttr("db") and
34-
result = django()
37+
result = DataFlow::importNode("django" + "." + attr_name)
3538
or
36-
exists(DataFlow::TypeTracker t2 | result = db(t2).track(t2, t))
37-
}
39+
t.startInAttr(attr_name) and
40+
result = DataFlow::importNode("django")
41+
)
42+
or
43+
// Due to bad performance when using normal setup with `django_attr(t2, attr_name).track(t2, t)`
44+
// we have inlined that code and forced a join
45+
exists(DataFlow::TypeTracker t2 |
46+
exists(DataFlow::StepSummary summary |
47+
django_attr_first_join(t2, attr_name, result, summary) and
48+
t = t2.append(summary)
49+
)
50+
)
51+
}
52+
53+
pragma[nomagic]
54+
private predicate django_attr_first_join(
55+
DataFlow::TypeTracker t2, string attr_name, DataFlow::Node res, DataFlow::StepSummary summary
56+
) {
57+
DataFlow::StepSummary::step(django_attr(t2, attr_name), res, summary)
58+
}
59+
60+
/**
61+
* Gets a reference to the attribute `attr_name` of the `django` module.
62+
* WARNING: Only holds for a few predefined attributes.
63+
*/
64+
private DataFlow::Node django_attr(string attr_name) {
65+
result = django_attr(DataFlow::TypeTracker::end(), attr_name)
66+
}
3867

68+
/** Provides models for the `django` module. */
69+
module django {
70+
// -------------------------------------------------------------------------
71+
// django.db
72+
// -------------------------------------------------------------------------
3973
/** Gets a reference to the `django.db` module. */
40-
DataFlow::Node db() { result = db(DataFlow::TypeTracker::end()) }
74+
DataFlow::Node db() { result = django_attr("db") }
4175

4276
/** Provides models for the `django.db` module. */
4377
module db {
@@ -242,7 +276,9 @@ private module Django {
242276

243277
DbConnectionExecute() { node.getFunction() = django::db::execute().asCfgNode() }
244278

245-
override DataFlow::Node getSql() { result.asCfgNode() = node.getArg(0) }
279+
override DataFlow::Node getSql() {
280+
result.asCfgNode() in [node.getArg(0), node.getArgByName("sql")]
281+
}
246282
}
247283

248284
/** A call to the `annotate` function on a model using a `RawSQL` argument. */

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ def test_plain():
1010
def test_context():
1111
with connection.cursor() as cursor:
1212
cursor.execute("some sql") # $getSql="some sql"
13+
cursor.execute(sql="some sql") # $getSql="some sql"
1314

1415

1516
class User(models.Model):

0 commit comments

Comments
 (0)