Python: Add ModuleVariableNode to dataflow

This commit is contained in:
Taus Brock-Nannestad
2020-09-14 14:57:32 +02:00
parent e0f5b208da
commit 5fb33c90bc
6 changed files with 182 additions and 10 deletions

View File

@@ -119,6 +119,12 @@ module EssaFlow {
nodeTo.(EssaNode).getVar() = p.getVariable() and
nodeFrom.(EssaNode).getVar() = p.getAnInput()
)
or
// Module variable read
nodeFrom.(ModuleVariableNode).getARead() = nodeTo
or
// Module variable write
nodeFrom = nodeTo.(ModuleVariableNode).getAWrite()
}
}
@@ -131,8 +137,10 @@ module EssaFlow {
* excludes SSA flow through instance fields.
*/
predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
not nodeFrom.(EssaNode).getVar() instanceof GlobalSsaVariable and
not nodeTo.(EssaNode).getVar() instanceof GlobalSsaVariable and
not nodeFrom.asVar() instanceof GlobalSsaVariable and
not nodeTo.asVar() instanceof GlobalSsaVariable and
not nodeFrom instanceof ModuleVariableNode and
not nodeTo instanceof ModuleVariableNode and
EssaFlow::essaFlowStep(update(nodeFrom), nodeTo)
}
@@ -365,15 +373,13 @@ string ppReprType(DataFlowType t) { none() }
* another. Additional steps specified by the configuration are *not*
* taken into account.
*/
predicate jumpStep(Node pred, Node succ) {
// As we have ESSA variables for global variables,
// we include ESSA flow steps involving global variables.
predicate jumpStep(Node nodeFrom, Node nodeTo) {
EssaFlow::essaFlowStep(nodeFrom, nodeTo) and
(
pred.(EssaNode).getVar() instanceof GlobalSsaVariable
nodeFrom instanceof ModuleVariableNode
or
succ.(EssaNode).getVar() instanceof GlobalSsaVariable
) and
EssaFlow::essaFlowStep(pred, succ)
nodeTo instanceof ModuleVariableNode
)
}
//--------

View File

@@ -23,7 +23,9 @@ newtype TNode =
/** A node corresponding to a control flow node. */
TCfgNode(DataFlowCfgNode node) or
/** A node representing the value of an object after a state change */
TPostUpdateNode(PreUpdateNode pre)
TPostUpdateNode(PreUpdateNode pre) or
/** A node representing a global (module-level) variable in a specific module */
TModuleVariableNode(Module m, GlobalVariable v) { v.getScope() = m and v.escapes() }
/**
* An element, viewed as a node in a data flow graph. Either an SSA variable
@@ -148,6 +150,35 @@ class ParameterNode extends EssaNode {
override DataFlowCallable getEnclosingCallable() { this.isParameterOf(result, _) }
}
class ModuleVariableNode extends Node, TModuleVariableNode {
Module mod;
GlobalVariable var;
ModuleVariableNode() { this = TModuleVariableNode(mod, var) }
override Scope getScope() { result = mod }
override string toString() {
result = "ModuleVariableNode for " + var.toString() + " in " + mod.toString()
}
/** Gets the module in which this variable appears. */
Module getModule() { result = mod }
/** Gets the global variable corresponding to this node. */
GlobalVariable getVariable() { result = var }
/** Gets a node that reads this variable. */
Node getARead() { result.asCfgNode() = var.getALoad().getAFlowNode() }
/** Gets an `EssaNode` that corresponds to an assignment of this global variable. */
Node getAWrite() {
exists(DefinitionNode defn |
result.asVar().getDefinition().(EssaNodeDefinition).definedBy(var, defn)
)
}
}
/**
* A guard that validates some expression.
*