mirror of
https://github.com/github/codeql.git
synced 2026-04-30 19:26:02 +02:00
Merge pull request #8890 from tausbn/python-add-global-attribute-writes
Python: Add support for global attribute writes
This commit is contained in:
@@ -92,6 +92,32 @@ private class AttributeAssignmentAsAttrWrite extends AttrWrite, CfgNode {
|
||||
override string getAttributeName() { result = node.getName() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An attribute assignment where the object is a global variable: `global_var.attr = value`.
|
||||
*
|
||||
* Syntactically, this is identical to the situation that is covered by
|
||||
* `AttributeAssignmentAsAttrWrite`, however in this case we want to behave as if the object that is
|
||||
* being written is the underlying `ModuleVariableNode`.
|
||||
*/
|
||||
private class GlobalAttributeAssignmentAsAttrWrite extends AttrWrite, CfgNode {
|
||||
override AttributeAssignmentNode node;
|
||||
|
||||
override Node getValue() { result.asCfgNode() = node.getValue() }
|
||||
|
||||
override Node getObject() {
|
||||
result.(ModuleVariableNode).getVariable() = node.getObject().getNode().(Name).getVariable()
|
||||
}
|
||||
|
||||
override ExprNode getAttributeNameExpr() {
|
||||
// Attribute names don't exist as `Node`s in the control flow graph, as they can only ever be
|
||||
// identifiers, and are therefore represented directly as strings.
|
||||
// Use `getAttributeName` to access the name of the attribute.
|
||||
none()
|
||||
}
|
||||
|
||||
override string getAttributeName() { result = node.getName() }
|
||||
}
|
||||
|
||||
/** Represents `CallNode`s that may refer to calls to built-in functions or classes. */
|
||||
private class BuiltInCallNode extends CallNode {
|
||||
string name;
|
||||
|
||||
@@ -49,6 +49,24 @@ def test_create_with_foo():
|
||||
x = create_with_foo() # $ tracked=foo
|
||||
print(x.foo) # $ tracked=foo tracked
|
||||
|
||||
def test_global_attribute_assignment():
|
||||
global global_var
|
||||
global_var.foo = tracked # $ tracked tracked=foo
|
||||
|
||||
def test_global_attribute_read():
|
||||
x = global_var.foo # $ tracked tracked=foo
|
||||
|
||||
def test_local_attribute_assignment():
|
||||
# Same as `test_global_attribute_assignment`, but the assigned variable is not global
|
||||
# In this case, we don't want flow going to the `ModuleVariableNode` for `local_var`
|
||||
# (which is referenced in `test_local_attribute_read`).
|
||||
local_var = object() # $ tracked=foo
|
||||
local_var.foo = tracked # $ tracked tracked=foo
|
||||
|
||||
def test_local_attribute_read():
|
||||
x = local_var.foo
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Attributes assigned statically to a class
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user