WIP: Flask View class modeling for restplus

Based on some DBs I had that contained dependencies
This commit is contained in:
Rasmus Wriedt Larsen
2023-06-19 10:47:56 +02:00
parent 6a48e6ed5e
commit 2f17d2f3ac
4 changed files with 62 additions and 15 deletions

View File

@@ -14,6 +14,7 @@ private import semmle.python.ApiGraphs
private import semmle.python.frameworks.internal.InstanceTaintStepsHelper
private import semmle.python.security.dataflow.PathInjectionCustomizations
private import semmle.python.dataflow.new.FlowSummary
private import semmle.python.frameworks.data.ModelsAsData
/**
* Provides models for the `flask` PyPI package.
@@ -39,6 +40,10 @@ module Flask {
"MethodView"
])
.getASubclass*()
or
result = ModelOutput::getATypeNode("flask.View~Subclass").getASubclass*()
or
result = ModelOutput::getATypeNode("flask.MethodView~Subclass").getASubclass*()
}
}
@@ -52,6 +57,8 @@ module Flask {
API::Node subclassRef() {
result =
API::moduleImport("flask").getMember("views").getMember("MethodView").getASubclass*()
or
result = ModelOutput::getATypeNode("flask.MethodView~Subclass").getASubclass*()
}
}
}

View File

@@ -23,7 +23,12 @@ extensions:
- addsTo:
pack: codeql/python-all
extensible: typeModel
data: []
data:
- ["flask.MethodView~Subclass","flask_restplus","Member[api].Member[SwaggerView]"]
- ["flask.MethodView~Subclass","flask_restplus","Member[resource].Member[Resource]"]
- ["flask.MethodView~Subclass","flask_restplus","Member[api].Member[Resource]"]
- ["flask.MethodView~Subclass","flask_restplus","Member[resource].Member[MethodView]"]
- ["flask.MethodView~Subclass","flask_restplus","Member[Resource]"]
- addsTo:
pack: codeql/python-all

View File

@@ -11,28 +11,17 @@ private import semmle.python.ApiGraphs
private import semmle.python.filters.Tests
// very much inspired by the draft at https://github.com/github/codeql/pull/5632
private module NotExposed {
module NotExposed {
// Instructions:
// This needs to be automated better, but for this prototype, here are some rough instructions:
// 0) get a database of the library you are about to model
// 1) fill out the `getAlreadyModeledClass` body below
// 2) quick-eval the `quickEvalMe` predicate below, and copy the output to your modeling predicate
class MySpec extends FindSubclassesSpec {
MySpec() { this = "MySpec" }
override API::Node getAlreadyModeledClass() {
// FILL ME OUT ! (but don't commit with any changes)
none()
// for example
// result = API::moduleImport("rest_framework").getMember("views").getMember("APIView")
}
}
predicate quickEvalMe(string newImport) {
newImport =
"// imports generated by python/frameworks/internal/SubclassFinder.qll\n" + "this = API::" +
concat(string newModelFullyQualified |
newModel(any(MySpec spec), newModelFullyQualified, _, _, _)
newModel(any(FindSubclassesSpec spec), newModelFullyQualified, _, _, _)
|
fullyQualifiedToApiGraphPath(newModelFullyQualified), " or this = API::"
)
@@ -76,6 +65,8 @@ private module NotExposed {
bindingset[this]
abstract class FindSubclassesSpec extends string {
abstract API::Node getAlreadyModeledClass();
FindSubclassesSpec getSuperClass() { none() }
}
/**
@@ -111,7 +102,7 @@ private module NotExposed {
predicate isNonTestProjectCode(AstNode ast) {
not ast.getScope*() instanceof TestScope and
not ast.getLocation().getFile().getRelativePath().matches("tests/%") and
exists(ast.getLocation().getFile().getRelativePath())
not exists(ast.getLocation().getFile().getRelativePath())
}
predicate hasAllStatement(Module mod) {