C++: Add VariableNode

This commit is contained in:
Jonas Jensen
2020-02-04 13:21:33 +01:00
parent 73e34f1447
commit 6d081a997a
2 changed files with 55 additions and 10 deletions

View File

@@ -185,7 +185,13 @@ class CastNode extends InstructionNode {
CastNode() { none() } // stub implementation
}
class DataFlowCallable = Function;
/**
* A function that may contain code or a variable that may contain itself. When
* flow crosses from one _enclosing callable_ to another, the interprocedural
* data-flow library discards call contexts and inserts a node in the big-step
* relation used for human-readable path explanations.
*/
class DataFlowCallable = Declaration;
class DataFlowExpr = Expr;

View File

@@ -8,12 +8,9 @@ private import semmle.code.cpp.controlflow.IRGuards
private import semmle.code.cpp.ir.ValueNumbering
private import semmle.code.cpp.models.interfaces.DataFlow
/**
* A newtype wrapper to prevent accidental casts between `Node` and
* `Instruction`. This ensures we can add `Node`s that are not `Instruction`s
* in the future.
*/
private newtype TIRDataFlowNode = TInstructionNode(Instruction i)
private newtype TIRDataFlowNode =
TInstructionNode(Instruction i) or
TVariableNode(Variable var)
/**
* A node in a data flow graph.
@@ -24,11 +21,11 @@ private newtype TIRDataFlowNode = TInstructionNode(Instruction i)
*/
class Node extends TIRDataFlowNode {
/**
* INTERNAL: Do not use. Alternative name for `getFunction`.
* INTERNAL: Do not use.
*/
Function getEnclosingCallable() { result = this.getFunction() }
Declaration getEnclosingCallable() { none() } // overridden in subclasses
/** Gets the function to which this node belongs. */
/** Gets the function to which this node belongs, if any. */
Function getFunction() { none() } // overridden in subclasses
/** Gets the type of this node. */
@@ -57,6 +54,12 @@ class Node extends TIRDataFlowNode {
/** Gets the parameter corresponding to this node, if any. */
Parameter asParameter() { result = this.(ParameterNode).getParameter() }
/**
* Gets the variable corresponding to this node, if any. This can be used for
* modelling flow in and out of global variables.
*/
Variable asVariable() { result = this.(VariableNode).getVariable() }
/**
* DEPRECATED: See UninitializedNode.
*
@@ -98,6 +101,8 @@ class InstructionNode extends Node, TInstructionNode {
/** Gets the instruction corresponding to this node. */
Instruction getInstruction() { result = instr }
override Declaration getEnclosingCallable() { result = this.getFunction() }
override Function getFunction() { result = instr.getEnclosingFunction() }
override Type getType() { result = instr.getResultType() }
@@ -236,6 +241,37 @@ class DefinitionByReferenceNode extends InstructionNode {
}
}
/**
* A `Node` corresponding to a variable in the program, as opposed to the
* value of that variable at some particular point. This can be used for
* modelling flow in and out of global variables.
*/
class VariableNode extends Node, TVariableNode {
Variable v;
VariableNode() { this = TVariableNode(v) }
/** Gets the variable corresponding to this node. */
Variable getVariable() { result = v }
override Function getFunction() { none() }
override Declaration getEnclosingCallable() {
// When flow crosses from one _enclosing callable_ to another, the
// interprocedural data-flow library discards call contexts and inserts a
// node in the big-step relation used for human-readable path explanations.
// Therefore we want a distinct enclosing callable for each `VariableNode`,
// and that can be the `Variable` itself.
result = v
}
override Type getType() { result = v.getType() }
override Location getLocation() { result = v.getLocation() }
override string toString() { result = v.toString() }
}
/**
* Gets the node corresponding to `instr`.
*/
@@ -260,6 +296,9 @@ ExprNode convertedExprNode(Expr e) { result.getExpr() = e }
*/
ParameterNode parameterNode(Parameter p) { result.getParameter() = p }
/** Gets the `VariableNode` corresponding to the variable `v`. */
VariableNode variableNode(Variable v) { result.getVariable() = v }
/**
* Gets the `Node` corresponding to the value of an uninitialized local
* variable `v`.