mirror of
https://github.com/github/codeql.git
synced 2025-12-20 10:46:30 +01:00
Python: refactor Node class
This commit is contained in:
@@ -40,15 +40,15 @@ module EssaFlow {
|
||||
// `x = f(42)`
|
||||
// nodeFrom is `f(42)`, cfg node
|
||||
// nodeTo is `x`, essa var
|
||||
nodeFrom.asCfgNode() = nodeTo.asEssaNode().getDefinition().(AssignmentDefinition).getValue()
|
||||
nodeFrom.(CfgNode).getNode() = nodeTo.(EssaNode).getVar().getDefinition().(AssignmentDefinition).getValue()
|
||||
or
|
||||
// With definition
|
||||
// `with f(42) as x:`
|
||||
// nodeFrom is `f(42)`, cfg node
|
||||
// nodeTo is `x`, essa var
|
||||
exists(With with, ControlFlowNode contextManager, ControlFlowNode var |
|
||||
nodeFrom.asCfgNode() = contextManager and
|
||||
nodeTo.asEssaNode().getDefinition().(WithDefinition).getDefiningNode() = var and
|
||||
nodeFrom.(CfgNode).getNode() = contextManager and
|
||||
nodeTo.(EssaNode).getVar().getDefinition().(WithDefinition).getDefiningNode() = var and
|
||||
// see `with_flow`
|
||||
with.getContextExpr() = contextManager.getNode() and
|
||||
with.getOptionalVars() = var.getNode() and
|
||||
@@ -60,22 +60,22 @@ module EssaFlow {
|
||||
// `x = f(y)`
|
||||
// nodeFrom is `y` on first line, essa var
|
||||
// nodeTo is `y` on second line, cfg node
|
||||
nodeFrom.asEssaNode().getAUse() = nodeTo.asCfgNode()
|
||||
nodeFrom.(EssaNode).getVar().getAUse() = nodeTo.(CfgNode).getNode()
|
||||
or
|
||||
// Refinements
|
||||
exists(EssaEdgeRefinement r |
|
||||
nodeTo.asEssaNode() = r.getVariable() and
|
||||
nodeFrom.asEssaNode() = r.getInput()
|
||||
nodeTo.(EssaNode).getVar() = r.getVariable() and
|
||||
nodeFrom.(EssaNode).getVar() = r.getInput()
|
||||
)
|
||||
or
|
||||
exists(EssaNodeRefinement r |
|
||||
nodeTo.asEssaNode() = r.getVariable() and
|
||||
nodeFrom.asEssaNode() = r.getInput()
|
||||
nodeTo.(EssaNode).getVar() = r.getVariable() and
|
||||
nodeFrom.(EssaNode).getVar() = r.getInput()
|
||||
)
|
||||
or
|
||||
exists(PhiFunction p |
|
||||
nodeTo.asEssaNode() = p.getVariable() and
|
||||
nodeFrom.asEssaNode() = p.getAnInput()
|
||||
nodeTo.(EssaNode).getVar() = p.getVariable() and
|
||||
nodeFrom.(EssaNode).getVar() = p.getAnInput()
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -119,19 +119,19 @@ class DataFlowCall extends CallNode {
|
||||
}
|
||||
|
||||
/** A data flow node that represents a call argument. */
|
||||
class ArgumentNode extends Node {
|
||||
class ArgumentNode extends CfgNode {
|
||||
ArgumentNode() {
|
||||
exists(DataFlowCall call, int pos |
|
||||
this.asCfgNode() = call.getArg(pos)
|
||||
node = call.getArg(pos)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if this argument occurs at the given position in the given call. */
|
||||
/** Holds if this argument occurs at the given position in the given call. */
|
||||
predicate argumentOf(DataFlowCall call, int pos) {
|
||||
this.asCfgNode() = call.getArg(pos)
|
||||
node = call.getArg(pos)
|
||||
}
|
||||
|
||||
/** Gets the call in which this node is an argument. */
|
||||
/** Gets the call in which this node is an argument. */
|
||||
final DataFlowCall getCall() { this.argumentOf(result, _) }
|
||||
}
|
||||
|
||||
@@ -152,31 +152,31 @@ class ReturnKind extends TReturnKind {
|
||||
}
|
||||
|
||||
/** A data flow node that represents a value returned by a callable. */
|
||||
class ReturnNode extends Node {
|
||||
class ReturnNode extends CfgNode {
|
||||
Return ret;
|
||||
|
||||
// See `TaintTrackingImplementation::returnFlowStep`
|
||||
// See `TaintTrackingImplementation::returnFlowStep`
|
||||
ReturnNode() {
|
||||
this.asCfgNode() = ret.getValue().getAFlowNode()
|
||||
node = ret.getValue().getAFlowNode()
|
||||
}
|
||||
|
||||
/** Gets the kind of this return node. */
|
||||
/** Gets the kind of this return node. */
|
||||
ReturnKind getKind() { result = TNormalReturnKind() }
|
||||
|
||||
override DataFlowCallable getEnclosingCallable() {
|
||||
override DataFlowCallable getEnclosingCallable() {
|
||||
result.getScope().getAStmt() = ret // TODO: check nested function definitions
|
||||
}
|
||||
}
|
||||
|
||||
/** A data flow node that represents the output of a call. */
|
||||
class OutNode extends Node {
|
||||
OutNode() { this.asCfgNode() instanceof CallNode }
|
||||
class OutNode extends CfgNode {
|
||||
OutNode() { node instanceof CallNode }
|
||||
|
||||
/** Gets the underlying call, where this node is a corresponding output of kind `kind`. */
|
||||
/** Gets the underlying call, where this node is a corresponding output of kind `kind`. */
|
||||
cached
|
||||
DataFlowCall getCall(ReturnKind kind) {
|
||||
kind = TNormalReturnKind() and
|
||||
result = this.asCfgNode()
|
||||
result = node
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,13 +231,13 @@ string ppReprType(DataFlowType t) { result = t.toString() }
|
||||
* another. Additional steps specified by the configuration are *not*
|
||||
* taken into account.
|
||||
*/
|
||||
predicate jumpStep(ExprNode pred, ExprNode succ) {
|
||||
predicate jumpStep(Node pred, Node succ) {
|
||||
// As we have ESSA variables for global variables,
|
||||
// we include ESSA flow steps involving global variables.
|
||||
(
|
||||
pred.asEssaNode() instanceof GlobalSsaVariable
|
||||
pred.(EssaNode).getVar() instanceof GlobalSsaVariable
|
||||
or
|
||||
succ.asEssaNode() instanceof GlobalSsaVariable
|
||||
succ.(EssaNode).getVar() instanceof GlobalSsaVariable
|
||||
) and
|
||||
EssaFlow::essaFlowStep(pred, succ)
|
||||
}
|
||||
|
||||
@@ -27,34 +27,23 @@ newtype TNode =
|
||||
* (`ExprNode`) or a parameter (`ParameterNode`).
|
||||
*/
|
||||
class Node extends TNode {
|
||||
|
||||
/**
|
||||
* Get the underlying SSA variable if this is such a node.
|
||||
*/
|
||||
EssaVariable asEssaNode() { this = TEssaNode(result) }
|
||||
|
||||
/**
|
||||
* Get the underlying ControlFlowNode if this is such a node.
|
||||
*/
|
||||
ControlFlowNode asCfgNode() { this = TCfgNode(result) }
|
||||
|
||||
/**
|
||||
* Get a string representation of this data flow node.
|
||||
*/
|
||||
string toString() {
|
||||
result = this.asEssaNode().toString()
|
||||
or
|
||||
result = this.asCfgNode().toString()
|
||||
}
|
||||
string toString() { result = "Data flow node" }
|
||||
|
||||
/** Gets the enclosing callable of this node. */
|
||||
/** Gets the scope of this node. */
|
||||
Scope getScope() { none() }
|
||||
|
||||
/** Gets the enclosing callable of this node. */
|
||||
DataFlowCallable getEnclosingCallable() {
|
||||
result.getScope() = this.asCfgNode().getNode().getScope() // this allows Cfg -> ESSA def
|
||||
or
|
||||
result.getScope() = this.asEssaNode().getScope() // this allows ESSA var -> Cfg use
|
||||
result.getScope() = this.getScope()
|
||||
}
|
||||
|
||||
/**
|
||||
/** Gets the location of this node */
|
||||
Location getLocation() { none() }
|
||||
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
@@ -64,12 +53,47 @@ class Node extends TNode {
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
this.asEssaNode().getDefinition().getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
or
|
||||
this.asCfgNode().getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
this.getLocation()
|
||||
.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
}
|
||||
|
||||
class EssaNode extends Node, TEssaNode {
|
||||
EssaVariable var;
|
||||
|
||||
EssaNode() { this = TEssaNode(var) }
|
||||
|
||||
EssaVariable getVar() { result = var }
|
||||
|
||||
/**
|
||||
* Get a string representation of this data flow node.
|
||||
*/
|
||||
override string toString() {
|
||||
result = var.toString()
|
||||
}
|
||||
|
||||
override Scope getScope() { result = var.getScope() }
|
||||
|
||||
override Location getLocation() { result = var.getDefinition().getLocation() }
|
||||
}
|
||||
|
||||
class CfgNode extends Node, TCfgNode {
|
||||
ControlFlowNode node;
|
||||
|
||||
CfgNode() { this = TCfgNode(node) }
|
||||
|
||||
ControlFlowNode getNode() { result = node }
|
||||
|
||||
/**
|
||||
* Get a string representation of this data flow node.
|
||||
*/
|
||||
override string toString() {
|
||||
result = node.toString()
|
||||
}
|
||||
|
||||
override Scope getScope() { result = node.getScope() }
|
||||
|
||||
override Location getLocation() { result = node.getLocation() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -89,22 +113,18 @@ ExprNode exprNode(DataFlowExpr e) { none() }
|
||||
* The value of a parameter at function entry, viewed as a node in a data
|
||||
* flow graph.
|
||||
*/
|
||||
class ParameterNode extends Node {
|
||||
ParameterNode() {
|
||||
this.asEssaNode() instanceof ParameterDefinition
|
||||
}
|
||||
class ParameterNode extends EssaNode {
|
||||
ParameterNode() { var instanceof ParameterDefinition }
|
||||
|
||||
/**
|
||||
/**
|
||||
* Holds if this node is the parameter of callable `c` at the specified
|
||||
* (zero-based) position.
|
||||
*/
|
||||
predicate isParameterOf(DataFlowCallable c, int i) {
|
||||
this.asEssaNode().(ParameterDefinition).getDefiningNode() = c.getParameter(i)
|
||||
var.(ParameterDefinition).getDefiningNode() = c.getParameter(i)
|
||||
}
|
||||
|
||||
override DataFlowCallable getEnclosingCallable() {
|
||||
this.isParameterOf(result, _)
|
||||
}
|
||||
override DataFlowCallable getEnclosingCallable() { this.isParameterOf(result, _) }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user