11import python
22import semmle.python.web.Http
3-
4- /** The flask module */
5- ModuleObject theFlaskModule ( ) {
6- result = ModuleObject:: named ( "flask" )
7- }
3+ import semmle.python.web.flask.Response
84
95/** The flask app class */
10- ClassObject theFlaskClass ( ) {
11- result = theFlaskModule ( ) .attr ( "Flask" )
12- }
6+ ClassValue theFlaskClass ( ) { result = Value:: named ( "flask.Flask" ) }
137
148/** The flask MethodView class */
15- ClassObject theFlaskMethodViewClass ( ) {
16- result = ModuleObject:: named ( "flask.views" ) .attr ( "MethodView" )
17- }
9+ ClassValue theFlaskMethodViewClass ( ) { result = Value:: named ( "flask.views.MethodView" ) }
1810
19- ClassObject theFlaskReponseClass ( ) {
20- result = theFlaskModule ( ) .attr ( "Response" )
21- }
11+ ClassValue theFlaskReponseClass ( ) { result = Value:: named ( "flask.Response" ) }
2212
23- /** Holds if `route` is routed to `func`
13+ /**
14+ * Holds if `route` is routed to `func`
2415 * by decorating `func` with `app.route(route)`
2516 */
2617predicate app_route ( ControlFlowNode route , Function func ) {
2718 exists ( CallNode route_call , CallNode decorator_call |
28- route_call .getFunction ( ) .( AttrNode ) .getObject ( "route" ) .refersTo ( _ , theFlaskClass ( ) , _ ) and
19+ route_call .getFunction ( ) .( AttrNode ) .getObject ( "route" ) .pointsTo ( ) . getClass ( ) = theFlaskClass ( ) and
2920 decorator_call .getFunction ( ) = route_call and
3021 route_call .getArg ( 0 ) = route and
3122 decorator_call .getArg ( 0 ) .getNode ( ) .( FunctionExpr ) .getInnerScope ( ) = func
@@ -35,30 +26,29 @@ predicate app_route(ControlFlowNode route, Function func) {
3526/* Helper for add_url_rule */
3627private predicate add_url_rule_call ( ControlFlowNode regex , ControlFlowNode callable ) {
3728 exists ( CallNode call |
38- call .getFunction ( ) .( AttrNode ) .getObject ( "add_url_rule" ) .refersTo ( _, theFlaskClass ( ) , _) and
39- regex = call .getArg ( 0 ) |
29+ call .getFunction ( ) .( AttrNode ) .getObject ( "add_url_rule" ) .pointsTo ( ) .getClass ( ) = theFlaskClass ( ) and
30+ regex = call .getArg ( 0 )
31+ |
4032 callable = call .getArg ( 2 ) or
4133 callable = call .getArgByName ( "view_func" )
4234 )
4335}
4436
4537/** Holds if urls matching `regex` are routed to `func` */
4638predicate add_url_rule ( ControlFlowNode regex , Function func ) {
47- exists ( ControlFlowNode callable |
48- add_url_rule_call ( regex , callable )
49- |
50- exists ( PyFunctionObject f | f .getFunction ( ) = func and callable .refersTo ( f ) )
39+ exists ( ControlFlowNode callable | add_url_rule_call ( regex , callable ) |
40+ exists ( PythonFunctionValue f | f .getScope ( ) = func and callable .pointsTo ( f ) )
5141 or
5242 /* MethodView.as_view() */
53- exists ( MethodViewClass view_cls |
54- view_cls .asTaint ( ) .taints ( callable ) |
55- func = view_cls .lookupAttribute ( httpVerbLower ( ) ) .( FunctionObject ) .getFunction ( )
43+ exists ( MethodViewClass view_cls | view_cls .asTaint ( ) .taints ( callable ) |
44+ func = view_cls .lookup ( httpVerbLower ( ) ) .( FunctionValue ) .getScope ( )
5645 )
57- /* TO DO -- Handle Views that aren't MethodViews */
46+ /* TODO: -- Handle Views that aren't MethodViews */
5847 )
5948}
6049
61- /** Holds if urls matching `regex` are routed to `func` using
50+ /**
51+ * Holds if urls matching `regex` are routed to `func` using
6252 * any of flask's routing mechanisms.
6353 */
6454predicate flask_routing ( ControlFlowNode regex , Function func ) {
@@ -68,65 +58,47 @@ predicate flask_routing(ControlFlowNode regex, Function func) {
6858}
6959
7060/** A class that extends flask.views.MethodView */
71- private class MethodViewClass extends ClassObject {
72-
73- MethodViewClass ( ) {
74- this .getAnImproperSuperType ( ) = theFlaskMethodViewClass ( )
75- }
61+ private class MethodViewClass extends ClassValue {
62+ MethodViewClass ( ) { this .getASuperType ( ) = theFlaskMethodViewClass ( ) }
7663
7764 /* As we are restricted to strings for taint kinds, we need to map these classes to strings. */
78- string taintString ( ) {
79- result = "flask/" + this .getQualifiedName ( ) + ".as.view"
80- }
65+ string taintString ( ) { result = "flask/" + this .getQualifiedName ( ) + ".as.view" }
8166
8267 /* As we are restricted to strings for taint kinds, we need to map these classes to strings. */
83- TaintKind asTaint ( ) {
84- result = this .taintString ( )
85- }
68+ TaintKind asTaint ( ) { result = this .taintString ( ) }
8669}
8770
8871private class MethodViewTaint extends TaintKind {
89-
90- MethodViewTaint ( ) {
91- any ( MethodViewClass cls ) .taintString ( ) = this
92- }
72+ MethodViewTaint ( ) { any ( MethodViewClass cls ) .taintString ( ) = this }
9373}
9474
9575/** A source of method view "taint"s. */
9676private class AsView extends TaintSource {
97-
9877 AsView ( ) {
99- exists ( ClassObject view_class |
100- view_class .getAnImproperSuperType ( ) = theFlaskMethodViewClass ( ) and
101- this .( CallNode ) .getFunction ( ) .( AttrNode ) .getObject ( "as_view" ) .refersTo ( view_class )
78+ exists ( ClassValue view_class |
79+ view_class .getASuperType ( ) = theFlaskMethodViewClass ( ) and
80+ this .( CallNode ) .getFunction ( ) .( AttrNode ) .getObject ( "as_view" ) .pointsTo ( view_class )
10281 )
10382 }
10483
105- override string toString ( ) {
106- result = "flask.MethodView.as_view()"
107- }
84+ override string toString ( ) { result = "flask.MethodView.as_view()" }
10885
10986 override predicate isSourceOf ( TaintKind kind ) {
11087 exists ( MethodViewClass view_class |
11188 kind = view_class .asTaint ( ) and
112- this .( CallNode ) .getFunction ( ) .( AttrNode ) .getObject ( "as_view" ) .refersTo ( view_class )
89+ this .( CallNode ) .getFunction ( ) .( AttrNode ) .getObject ( "as_view" ) .pointsTo ( view_class )
11390 )
11491 }
115-
11692}
11793
118-
11994class FlaskCookieSet extends CookieSet , CallNode {
120-
12195 FlaskCookieSet ( ) {
122- this .getFunction ( ) .( AttrNode ) .getObject ( "set_cookie" ) . refersTo ( _ , theFlaskReponseClass ( ) , _ )
96+ any ( FlaskResponseTaintKind t ) . taints ( this .getFunction ( ) .( AttrNode ) .getObject ( "set_cookie" ) )
12397 }
12498
12599 override string toString ( ) { result = CallNode .super .toString ( ) }
126100
127101 override ControlFlowNode getKey ( ) { result = this .getArg ( 0 ) }
128102
129103 override ControlFlowNode getValue ( ) { result = this .getArg ( 1 ) }
130-
131-
132104}
0 commit comments