@@ -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 */
1414private 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. */
0 commit comments