Python: API-graphs: allow class decorators in .getASubclass()

This commit is contained in:
Rasmus Wriedt Larsen
2022-06-15 17:30:21 +02:00
parent 5f32f898d5
commit d6e68258a4
3 changed files with 17 additions and 3 deletions

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Change `.getASubclass()` on `API::Node` so it allows to follow subclasses even if the class has a class decorator.

View File

@@ -591,8 +591,18 @@ module API {
or
// Subclassing a node
lbl = Label::subclass() and
exists(DataFlow::Node superclass | pred.flowsTo(superclass) |
ref.asExpr().(PY::ClassExpr).getABase() = superclass.asExpr()
exists(PY::ClassExpr clsExpr, DataFlow::Node superclass | pred.flowsTo(superclass) |
clsExpr.getABase() = superclass.asExpr() and
// Potentially a class decorator could do anything, but we assume they are
// "benign" and let subclasses edges flow through anyway.
// see example in https://github.com/django/django/blob/c2250cfb80e27cdf8d098428824da2800a18cadf/tests/auth_tests/test_views.py#L40-L46
(
not exists(clsExpr.getADecorator()) and
ref.asExpr() = clsExpr
or
ref.asExpr() = clsExpr.getADecoratorCall() and
not exists(PY::Call otherDecorator | otherDecorator.getArg(0) = ref.asExpr())
)
)
or
// awaiting

View File

@@ -30,5 +30,5 @@ def my_class_decorator(cls):
class MyViewWithDecorator(View): #$ use=moduleImport("flask").getMember("views").getMember("View").getASubclass()
pass
class SubclassFromDecorated(MyViewWithDecorator): #$ MISSING: use=moduleImport("flask").getMember("views").getMember("View").getASubclass().getASubclass()
class SubclassFromDecorated(MyViewWithDecorator): #$ use=moduleImport("flask").getMember("views").getMember("View").getASubclass().getASubclass()
pass