mirror of
https://github.com/github/codeql.git
synced 2025-12-20 10:46:30 +01:00
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.
This commit is contained in:
@@ -76,17 +76,10 @@ private module FlaskModel {
|
|||||||
// flask.views
|
// flask.views
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
/** Gets a reference to the `flask.views` module. */
|
/** Gets a reference to the `flask.views` module. */
|
||||||
DataFlow::Node views() { result = flask_attr("views").getAUse() }
|
API::Node views() { result = flask_attr("views") }
|
||||||
|
|
||||||
/** Provides models for the `flask.views` module */
|
/** Provides models for the `flask.views` module */
|
||||||
module views {
|
module views {
|
||||||
/**
|
|
||||||
* Gets a reference to the attribute `attr_name` of the `flask.views` module.
|
|
||||||
*/
|
|
||||||
private DataFlow::Node views_attr(string attr_name) {
|
|
||||||
result = flask().getMember("views").getMember(attr_name).getAUse()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides models for the `flask.views.View` class and subclasses.
|
* Provides models for the `flask.views.View` class and subclasses.
|
||||||
*
|
*
|
||||||
@@ -94,18 +87,9 @@ private module FlaskModel {
|
|||||||
*/
|
*/
|
||||||
module View {
|
module View {
|
||||||
/** Gets a reference to the `flask.views.View` class or any subclass. */
|
/** Gets a reference to the `flask.views.View` class or any subclass. */
|
||||||
private DataFlow::Node subclassRef(DataFlow::TypeTracker t) {
|
API::Node subclassRef() {
|
||||||
t.start() and
|
result = views().getMember(["View", "MethodView"]).getASubclass*()
|
||||||
result = views_attr(["View", "MethodView"])
|
|
||||||
or
|
|
||||||
// subclasses in project code
|
|
||||||
result.asExpr().(ClassExpr).getABase() = subclassRef(t.continue()).asExpr()
|
|
||||||
or
|
|
||||||
exists(DataFlow::TypeTracker t2 | result = subclassRef(t2).track(t2, t))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets a reference to the `flask.views.View` class or any subclass. */
|
|
||||||
DataFlow::Node subclassRef() { result = subclassRef(DataFlow::TypeTracker::end()) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -114,19 +98,8 @@ private module FlaskModel {
|
|||||||
* See https://flask.palletsprojects.com/en/1.1.x/views/#method-based-dispatching.
|
* See https://flask.palletsprojects.com/en/1.1.x/views/#method-based-dispatching.
|
||||||
*/
|
*/
|
||||||
module MethodView {
|
module MethodView {
|
||||||
/** Gets a reference to the `flask.views.View` class or any subclass. */
|
/** Gets a reference to the `flask.views.MethodView` class or any subclass. */
|
||||||
private DataFlow::Node subclassRef(DataFlow::TypeTracker t) {
|
API::Node subclassRef() { result = views().getMember("MethodView").getASubclass*() }
|
||||||
t.start() and
|
|
||||||
result = views_attr("MethodView")
|
|
||||||
or
|
|
||||||
// subclasses in project code
|
|
||||||
result.asExpr().(ClassExpr).getABase() = subclassRef(t.continue()).asExpr()
|
|
||||||
or
|
|
||||||
exists(DataFlow::TypeTracker t2 | result = subclassRef(t2).track(t2, t))
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets a reference to the `flask.views.View` class or any subclass. */
|
|
||||||
DataFlow::Node subclassRef() { result = subclassRef(DataFlow::TypeTracker::end()) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -155,7 +128,7 @@ private module FlaskModel {
|
|||||||
private class ClassInstantiation extends InstanceSource, DataFlow::CfgNode {
|
private class ClassInstantiation extends InstanceSource, DataFlow::CfgNode {
|
||||||
override CallNode node;
|
override CallNode node;
|
||||||
|
|
||||||
ClassInstantiation() { node.getFunction() = classRef().getAUse().asCfgNode() }
|
ClassInstantiation() { node = classRef().getACall().asCfgNode() }
|
||||||
|
|
||||||
override DataFlow::Node getBody() { result.asCfgNode() = node.getArg(0) }
|
override DataFlow::Node getBody() { result.asCfgNode() = node.getArg(0) }
|
||||||
|
|
||||||
@@ -189,7 +162,12 @@ private module FlaskModel {
|
|||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
/** A flask View class defined in project code. */
|
/** A flask View class defined in project code. */
|
||||||
class FlaskViewClassDef extends Class {
|
class FlaskViewClassDef extends Class {
|
||||||
FlaskViewClassDef() { this.getABase() = flask::views::View::subclassRef().asExpr() }
|
API::Node api_node;
|
||||||
|
|
||||||
|
FlaskViewClassDef() {
|
||||||
|
this.getABase() = flask::views::View::subclassRef().getAUse().asExpr() and
|
||||||
|
api_node.getAnImmediateUse().asExpr().(ClassExpr) = this.getParent()
|
||||||
|
}
|
||||||
|
|
||||||
/** Gets a function that could handle incoming requests, if any. */
|
/** Gets a function that could handle incoming requests, if any. */
|
||||||
Function getARequestHandler() {
|
Function getARequestHandler() {
|
||||||
@@ -199,42 +177,15 @@ private module FlaskModel {
|
|||||||
result.getName() = "dispatch_request"
|
result.getName() = "dispatch_request"
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets a reference to this class. */
|
|
||||||
private DataFlow::Node getARef(DataFlow::TypeTracker t) {
|
|
||||||
t.start() and
|
|
||||||
result.asExpr().(ClassExpr) = this.getParent()
|
|
||||||
or
|
|
||||||
exists(DataFlow::TypeTracker t2 | result = this.getARef(t2).track(t2, t))
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets a reference to this class. */
|
|
||||||
DataFlow::Node getARef() { result = this.getARef(DataFlow::TypeTracker::end()) }
|
|
||||||
|
|
||||||
/** Gets a reference to the `as_view` classmethod of this class. */
|
|
||||||
private DataFlow::Node asViewRef(DataFlow::TypeTracker t) {
|
|
||||||
t.startInAttr("as_view") and
|
|
||||||
result = this.getARef()
|
|
||||||
or
|
|
||||||
exists(DataFlow::TypeTracker t2 | result = this.asViewRef(t2).track(t2, t))
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets a reference to the `as_view` classmethod of this class. */
|
|
||||||
DataFlow::Node asViewRef() { result = this.asViewRef(DataFlow::TypeTracker::end()) }
|
|
||||||
|
|
||||||
/** Gets a reference to the result of calling the `as_view` classmethod of this class. */
|
/** Gets a reference to the result of calling the `as_view` classmethod of this class. */
|
||||||
private DataFlow::Node asViewResult(DataFlow::TypeTracker t) {
|
API::Node asViewResult() { result = api_node.getMember("as_view").getReturn() }
|
||||||
t.start() and
|
|
||||||
result.asCfgNode().(CallNode).getFunction() = this.asViewRef().asCfgNode()
|
|
||||||
or
|
|
||||||
exists(DataFlow::TypeTracker t2 | result = asViewResult(t2).track(t2, t))
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets a reference to the result of calling the `as_view` classmethod of this class. */
|
|
||||||
DataFlow::Node asViewResult() { result = asViewResult(DataFlow::TypeTracker::end()) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class FlaskMethodViewClassDef extends FlaskViewClassDef {
|
class FlaskMethodViewClassDef extends FlaskViewClassDef {
|
||||||
FlaskMethodViewClassDef() { this.getABase() = flask::views::MethodView::subclassRef().asExpr() }
|
FlaskMethodViewClassDef() {
|
||||||
|
this.getABase() = flask::views::MethodView::subclassRef().getAUse().asExpr() and
|
||||||
|
api_node.getAnImmediateUse().asExpr().(ClassExpr) = this.getParent()
|
||||||
|
}
|
||||||
|
|
||||||
override Function getARequestHandler() {
|
override Function getARequestHandler() {
|
||||||
result = super.getARequestHandler()
|
result = super.getARequestHandler()
|
||||||
@@ -316,7 +267,7 @@ private module FlaskModel {
|
|||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(FlaskViewClassDef vc |
|
exists(FlaskViewClassDef vc |
|
||||||
getViewArg() = vc.asViewResult() and
|
getViewArg() = vc.asViewResult().getAUse() and
|
||||||
result = vc.getARequestHandler()
|
result = vc.getARequestHandler()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user