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

Skip to content

Commit 3d2548e

Browse files
committed
Python: Get rid of remaining type trackers in Flask model
At this point, we may want to reconsider whether we really want the deeply-nested module structure we had before (and which made the type trackers somewhat bearable). There's also a question of how we can make this a bit more smooth. I think we need to consider exactly how we would like the interface to this to work.
1 parent 5bfde2c commit 3d2548e

1 file changed

Lines changed: 18 additions & 67 deletions

File tree

  • python/ql/src/semmle/python/frameworks

python/ql/src/semmle/python/frameworks/Flask.qll

Lines changed: 18 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -76,36 +76,20 @@ private module FlaskModel {
7676
// flask.views
7777
// -------------------------------------------------------------------------
7878
/** Gets a reference to the `flask.views` module. */
79-
DataFlow::Node views() { result = flask_attr("views").getAUse() }
79+
API::Node views() { result = flask_attr("views") }
8080

8181
/** Provides models for the `flask.views` module */
8282
module views {
83-
/**
84-
* Gets a reference to the attribute `attr_name` of the `flask.views` module.
85-
*/
86-
private DataFlow::Node views_attr(string attr_name) {
87-
result = flask().getMember("views").getMember(attr_name).getAUse()
88-
}
89-
9083
/**
9184
* Provides models for the `flask.views.View` class and subclasses.
9285
*
9386
* See https://flask.palletsprojects.com/en/1.1.x/views/#basic-principle.
9487
*/
9588
module View {
9689
/** Gets a reference to the `flask.views.View` class or any subclass. */
97-
private DataFlow::Node subclassRef(DataFlow::TypeTracker t) {
98-
t.start() and
99-
result = views_attr(["View", "MethodView"])
100-
or
101-
// subclasses in project code
102-
result.asExpr().(ClassExpr).getABase() = subclassRef(t.continue()).asExpr()
103-
or
104-
exists(DataFlow::TypeTracker t2 | result = subclassRef(t2).track(t2, t))
90+
API::Node subclassRef() {
91+
result = views().getMember(["View", "MethodView"]).getASubclass*()
10592
}
106-
107-
/** Gets a reference to the `flask.views.View` class or any subclass. */
108-
DataFlow::Node subclassRef() { result = subclassRef(DataFlow::TypeTracker::end()) }
10993
}
11094

11195
/**
@@ -114,19 +98,8 @@ private module FlaskModel {
11498
* See https://flask.palletsprojects.com/en/1.1.x/views/#method-based-dispatching.
11599
*/
116100
module MethodView {
117-
/** Gets a reference to the `flask.views.View` class or any subclass. */
118-
private DataFlow::Node subclassRef(DataFlow::TypeTracker t) {
119-
t.start() and
120-
result = views_attr("MethodView")
121-
or
122-
// subclasses in project code
123-
result.asExpr().(ClassExpr).getABase() = subclassRef(t.continue()).asExpr()
124-
or
125-
exists(DataFlow::TypeTracker t2 | result = subclassRef(t2).track(t2, t))
126-
}
127-
128-
/** Gets a reference to the `flask.views.View` class or any subclass. */
129-
DataFlow::Node subclassRef() { result = subclassRef(DataFlow::TypeTracker::end()) }
101+
/** Gets a reference to the `flask.views.MethodView` class or any subclass. */
102+
API::Node subclassRef() { result = views().getMember("MethodView").getASubclass*() }
130103
}
131104
}
132105
}
@@ -155,7 +128,7 @@ private module FlaskModel {
155128
private class ClassInstantiation extends InstanceSource, DataFlow::CfgNode {
156129
override CallNode node;
157130

158-
ClassInstantiation() { node.getFunction() = classRef().getAUse().asCfgNode() }
131+
ClassInstantiation() { node = classRef().getACall().asCfgNode() }
159132

160133
override DataFlow::Node getBody() { result.asCfgNode() = node.getArg(0) }
161134

@@ -189,7 +162,12 @@ private module FlaskModel {
189162
// ---------------------------------------------------------------------------
190163
/** A flask View class defined in project code. */
191164
class FlaskViewClassDef extends Class {
192-
FlaskViewClassDef() { this.getABase() = flask::views::View::subclassRef().asExpr() }
165+
API::Node api_node;
166+
167+
FlaskViewClassDef() {
168+
this.getABase() = flask::views::View::subclassRef().getAUse().asExpr() and
169+
api_node.getAnImmediateUse().asExpr().(ClassExpr) = this.getParent()
170+
}
193171

194172
/** Gets a function that could handle incoming requests, if any. */
195173
Function getARequestHandler() {
@@ -199,42 +177,15 @@ private module FlaskModel {
199177
result.getName() = "dispatch_request"
200178
}
201179

202-
/** Gets a reference to this class. */
203-
private DataFlow::Node getARef(DataFlow::TypeTracker t) {
204-
t.start() and
205-
result.asExpr().(ClassExpr) = this.getParent()
206-
or
207-
exists(DataFlow::TypeTracker t2 | result = this.getARef(t2).track(t2, t))
208-
}
209-
210-
/** Gets a reference to this class. */
211-
DataFlow::Node getARef() { result = this.getARef(DataFlow::TypeTracker::end()) }
212-
213-
/** Gets a reference to the `as_view` classmethod of this class. */
214-
private DataFlow::Node asViewRef(DataFlow::TypeTracker t) {
215-
t.startInAttr("as_view") and
216-
result = this.getARef()
217-
or
218-
exists(DataFlow::TypeTracker t2 | result = this.asViewRef(t2).track(t2, t))
219-
}
220-
221-
/** Gets a reference to the `as_view` classmethod of this class. */
222-
DataFlow::Node asViewRef() { result = this.asViewRef(DataFlow::TypeTracker::end()) }
223-
224-
/** Gets a reference to the result of calling the `as_view` classmethod of this class. */
225-
private DataFlow::Node asViewResult(DataFlow::TypeTracker t) {
226-
t.start() and
227-
result.asCfgNode().(CallNode).getFunction() = this.asViewRef().asCfgNode()
228-
or
229-
exists(DataFlow::TypeTracker t2 | result = asViewResult(t2).track(t2, t))
230-
}
231-
232180
/** Gets a reference to the result of calling the `as_view` classmethod of this class. */
233-
DataFlow::Node asViewResult() { result = asViewResult(DataFlow::TypeTracker::end()) }
181+
API::Node asViewResult() { result = api_node.getMember("as_view").getReturn() }
234182
}
235183

236184
class FlaskMethodViewClassDef extends FlaskViewClassDef {
237-
FlaskMethodViewClassDef() { this.getABase() = flask::views::MethodView::subclassRef().asExpr() }
185+
FlaskMethodViewClassDef() {
186+
this.getABase() = flask::views::MethodView::subclassRef().getAUse().asExpr() and
187+
api_node.getAnImmediateUse().asExpr().(ClassExpr) = this.getParent()
188+
}
238189

239190
override Function getARequestHandler() {
240191
result = super.getARequestHandler()
@@ -316,7 +267,7 @@ private module FlaskModel {
316267
)
317268
or
318269
exists(FlaskViewClassDef vc |
319-
getViewArg() = vc.asViewResult() and
270+
getViewArg() = vc.asViewResult().getAUse() and
320271
result = vc.getARequestHandler()
321272
)
322273
}

0 commit comments

Comments
 (0)