mirror of
https://github.com/github/codeql.git
synced 2026-04-27 09:45:15 +02:00
Python: Add basic flow for class attributes
This commit is contained in:
@@ -846,10 +846,27 @@ predicate comprehensionStoreStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) {
|
||||
* ```
|
||||
* data flows from `x` to the attribute `foo` of (the post-update node for) `obj`.
|
||||
*/
|
||||
predicate attributeStoreStep(Node nodeFrom, AttributeContent c, PostUpdateNode nodeTo) {
|
||||
exists(AttrWrite write |
|
||||
write.accesses(nodeTo.getPreUpdateNode(), c.getAttribute()) and
|
||||
nodeFrom = write.getValue()
|
||||
predicate attributeStoreStep(Node nodeFrom, AttributeContent c, Node nodeTo) {
|
||||
exists(Node object |
|
||||
// normally we target any PostUpdateNode. However, for class definitions the class
|
||||
// is only constructed after evaluating its' entire scope, so in terms of python
|
||||
// evaluations there is no post or pre update nodes, just one node for the class
|
||||
// expression. Therefore we target the class expression directly.
|
||||
//
|
||||
// Note: Due to the way we handle decorators, using a class decorator will result in
|
||||
// there being a post-update node for the class (argument to the decorator). We do
|
||||
// not want to differentiate between these two cases, so still target the class
|
||||
// expression directly.
|
||||
object = nodeTo.(PostUpdateNode).getPreUpdateNode() and
|
||||
not object.asExpr() instanceof ClassExpr
|
||||
or
|
||||
object = nodeTo and
|
||||
object.asExpr() instanceof ClassExpr
|
||||
|
|
||||
exists(AttrWrite write |
|
||||
write.accesses(object, c.getAttribute()) and
|
||||
nodeFrom = write.getValue()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -248,15 +248,24 @@ class WithTuple:
|
||||
SINK(self.my_tuple[0]) # $ MISSING: flow
|
||||
SINK_F(self.my_tuple[1])
|
||||
|
||||
def test_inst_no_call(self):
|
||||
SINK(self.my_tuple[0]) # $ MISSING: flow
|
||||
SINK_F(self.my_tuple[1])
|
||||
|
||||
@classmethod
|
||||
def test_cm(cls):
|
||||
SINK(cls.my_tuple[0]) # $ MISSING: flow
|
||||
SINK(cls.my_tuple[0]) # $ flow="SOURCE, l:-12 -> cls.my_tuple[0]"
|
||||
SINK_F(cls.my_tuple[1])
|
||||
|
||||
@classmethod
|
||||
def test_cm_no_call(cls):
|
||||
SINK(cls.my_tuple[0]) # $ MISSING: flow="SOURCE, l:-8 -> cls.my_tuple[0]"
|
||||
SINK_F(cls.my_tuple[1])
|
||||
|
||||
|
||||
@expects(2*4) # $ unresolved_call=expects(..) unresolved_call=expects(..)(..)
|
||||
def test_WithTuple():
|
||||
SINK(WithTuple.my_tuple[0]) # $ MISSING: flow="SOURCE, l:-7 -> WithTuple.my_tuple[0]"
|
||||
SINK(WithTuple.my_tuple[0]) # $ flow="SOURCE, l:-23 -> WithTuple.my_tuple[0]"
|
||||
SINK_F(WithTuple.my_tuple[1])
|
||||
|
||||
WithTuple.test_cm()
|
||||
@@ -264,7 +273,7 @@ def test_WithTuple():
|
||||
inst = WithTuple()
|
||||
inst.test_inst()
|
||||
|
||||
SINK(inst.my_tuple[0]) # $ MISSING: flow="SOURCE, l:-18 -> inst.my_tuple[0]"
|
||||
SINK(inst.my_tuple[0]) # $ MISSING: flow
|
||||
SINK_F(inst.my_tuple[1])
|
||||
|
||||
|
||||
@@ -279,7 +288,7 @@ def test_inst_override():
|
||||
SINK_F(inst.my_tuple[0])
|
||||
SINK(inst.my_tuple[1]) # $ flow="SOURCE, l:-3 -> inst.my_tuple[1]"
|
||||
|
||||
SINK(WithTuple.my_tuple[0]) # $ MISSING: flow="SOURCE, l:-27 -> WithTuple.my_tuple[0]"
|
||||
SINK(WithTuple.my_tuple[0]) # $ flow="SOURCE, l:-46 -> WithTuple.my_tuple[0]"
|
||||
SINK_F(WithTuple.my_tuple[1])
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user