@@ -15,6 +15,9 @@ private import experimental.semmle.python.frameworks.Werkzeug
1515 * See https://flask.palletsprojects.com/en/1.1.x/.
1616 */
1717private module FlaskModel {
18+ // ---------------------------------------------------------------------------
19+ // flask
20+ // ---------------------------------------------------------------------------
1821 /** Gets a reference to the `flask` module. */
1922 private DataFlow:: Node flask ( DataFlow:: TypeTracker t ) {
2023 t .start ( ) and
@@ -26,21 +29,49 @@ private module FlaskModel {
2629 /** Gets a reference to the `flask` module. */
2730 DataFlow:: Node flask ( ) { result = flask ( DataFlow:: TypeTracker:: end ( ) ) }
2831
29- /** Provides models for the `flask` module. */
30- module flask {
31- /** Gets a reference to the `flask.request` object. */
32- private DataFlow:: Node request ( DataFlow:: TypeTracker t ) {
32+ /**
33+ * Gets a reference to the attribute `attr_name` of the `flask` module.
34+ * WARNING: Only holds for a few predefined attributes.
35+ */
36+ private DataFlow:: Node flask_attr ( DataFlow:: TypeTracker t , string attr_name ) {
37+ attr_name in [ "request" ] and
38+ (
3339 t .start ( ) and
34- result = DataFlow:: importNode ( "flask.request" )
40+ result = DataFlow:: importNode ( "flask" + "." + attr_name )
3541 or
36- t .startInAttr ( "request" ) and
42+ t .startInAttr ( attr_name ) and
3743 result = flask ( )
38- or
39- exists ( DataFlow:: TypeTracker t2 | result = request ( t2 ) .track ( t2 , t ) )
40- }
44+ )
45+ or
46+ // Due to bad performance when using normal setup with `flask_attr(t2, attr_name).track(t2, t)`
47+ // we have inlined that code and forced a join
48+ exists ( DataFlow:: TypeTracker t2 |
49+ exists ( DataFlow:: StepSummary summary |
50+ flask_attr_first_join ( t2 , attr_name , result , summary ) and
51+ t = t2 .append ( summary )
52+ )
53+ )
54+ }
55+
56+ pragma [ nomagic]
57+ private predicate flask_attr_first_join (
58+ DataFlow:: TypeTracker t2 , string attr_name , DataFlow:: Node res , DataFlow:: StepSummary summary
59+ ) {
60+ DataFlow:: StepSummary:: step ( flask_attr ( t2 , attr_name ) , res , summary )
61+ }
62+
63+ /**
64+ * Gets a reference to the attribute `attr_name` of the `flask` module.
65+ * WARNING: Only holds for a few predefined attributes.
66+ */
67+ private DataFlow:: Node flask_attr ( string attr_name ) {
68+ result = flask_attr ( DataFlow:: TypeTracker:: end ( ) , attr_name )
69+ }
4170
71+ /** Provides models for the `flask` module. */
72+ module flask {
4273 /** Gets a reference to the `flask.request` object. */
43- DataFlow:: Node request ( ) { result = request ( DataFlow :: TypeTracker :: end ( ) ) }
74+ DataFlow:: Node request ( ) { result = flask_attr ( "request" ) }
4475
4576 /**
4677 * Provides models for the `flask.Flask` class
0 commit comments