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

Skip to content

Commit 7f3c6ac

Browse files
committed
Python: Handle class attribute references in API graph
This is slightly dubious, and should really be in the currently unimplemented "def" counterpart to the "use" bits we already have. However, it seems to work correctly, and in the spirit of moving things along, this seemed like the easier solution. We can always replace the implementation with the "proper" approach at a later point.
1 parent ef60057 commit 7f3c6ac

2 files changed

Lines changed: 8 additions & 4 deletions

File tree

python/ql/src/semmle/python/ApiGraphs.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -356,9 +356,9 @@ module API {
356356
// the relationship between `pred` and `ref`.
357357
use(base, src) and pred = trackUseNode(src)
358358
|
359-
// Reading an attribute on a node that is a use of `base`:
359+
// Referring to an attribute on a node that is a use of `base`:
360360
lbl = Label::memberFromRef(ref) and
361-
ref = pred.getAnAttributeRead()
361+
ref = pred.getAnAttributeReference()
362362
or
363363
// Calling a node that is a use of `base`
364364
lbl = Label::return() and

python/ql/test/experimental/dataflow/ApiGraphs/test.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,13 +86,17 @@ def f():
8686
from flask.views import View #$ use=moduleImport("flask").getMember("views").getMember("View")
8787

8888
class MyView(View): #$ use=moduleImport("flask").getMember("views").getMember("View").getASubclass()
89-
pass
89+
myvar = 45 #$ use=moduleImport("flask").getMember("views").getMember("View").getASubclass().getMember("myvar")
90+
def my_method(self): #$ use=moduleImport("flask").getMember("views").getMember("View").getASubclass().getMember("my_method")
91+
pass
9092

9193
instance = MyView() #$ use=moduleImport("flask").getMember("views").getMember("View").getASubclass().getReturn()
9294

9395
def internal():
9496
from pflask.views import View #$ use=moduleImport("pflask").getMember("views").getMember("View")
9597
class IntMyView(View): #$ use=moduleImport("pflask").getMember("views").getMember("View").getASubclass()
96-
pass
98+
my_internal_var = 35 #$ use=moduleImport("pflask").getMember("views").getMember("View").getASubclass().getMember("my_internal_var")
99+
def my_internal_method(self): #$ use=moduleImport("pflask").getMember("views").getMember("View").getASubclass().getMember("my_internal_method")
100+
pass
97101

98102
int_instance = IntMyView() #$ use=moduleImport("pflask").getMember("views").getMember("View").getASubclass().getReturn()

0 commit comments

Comments
 (0)