@@ -8,12 +8,9 @@ private import semmle.code.cpp.controlflow.IRGuards
88private import semmle.code.cpp.ir.ValueNumbering
99private import semmle.code.cpp.models.interfaces.DataFlow
1010
11- /**
12- * A newtype wrapper to prevent accidental casts between `Node` and
13- * `Instruction`. This ensures we can add `Node`s that are not `Instruction`s
14- * in the future.
15- */
16- private newtype TIRDataFlowNode = TInstructionNode ( Instruction i )
11+ private newtype TIRDataFlowNode =
12+ TInstructionNode ( Instruction i ) or
13+ TVariableNode ( Variable var )
1714
1815/**
1916 * A node in a data flow graph.
@@ -24,11 +21,11 @@ private newtype TIRDataFlowNode = TInstructionNode(Instruction i)
2421 */
2522class Node extends TIRDataFlowNode {
2623 /**
27- * INTERNAL: Do not use. Alternative name for `getFunction`.
24+ * INTERNAL: Do not use.
2825 */
29- Function getEnclosingCallable ( ) { result = this . getFunction ( ) }
26+ Declaration getEnclosingCallable ( ) { none ( ) } // overridden in subclasses
3027
31- /** Gets the function to which this node belongs. */
28+ /** Gets the function to which this node belongs, if any . */
3229 Function getFunction ( ) { none ( ) } // overridden in subclasses
3330
3431 /** Gets the type of this node. */
@@ -57,6 +54,12 @@ class Node extends TIRDataFlowNode {
5754 /** Gets the parameter corresponding to this node, if any. */
5855 Parameter asParameter ( ) { result = this .( ParameterNode ) .getParameter ( ) }
5956
57+ /**
58+ * Gets the variable corresponding to this node, if any. This can be used for
59+ * modelling flow in and out of global variables.
60+ */
61+ Variable asVariable ( ) { result = this .( VariableNode ) .getVariable ( ) }
62+
6063 /**
6164 * DEPRECATED: See UninitializedNode.
6265 *
@@ -98,6 +101,8 @@ class InstructionNode extends Node, TInstructionNode {
98101 /** Gets the instruction corresponding to this node. */
99102 Instruction getInstruction ( ) { result = instr }
100103
104+ override Declaration getEnclosingCallable ( ) { result = this .getFunction ( ) }
105+
101106 override Function getFunction ( ) { result = instr .getEnclosingFunction ( ) }
102107
103108 override Type getType ( ) { result = instr .getResultType ( ) }
@@ -236,6 +241,37 @@ class DefinitionByReferenceNode extends InstructionNode {
236241 }
237242}
238243
244+ /**
245+ * A `Node` corresponding to a variable in the program, as opposed to the
246+ * value of that variable at some particular point. This can be used for
247+ * modelling flow in and out of global variables.
248+ */
249+ class VariableNode extends Node , TVariableNode {
250+ Variable v ;
251+
252+ VariableNode ( ) { this = TVariableNode ( v ) }
253+
254+ /** Gets the variable corresponding to this node. */
255+ Variable getVariable ( ) { result = v }
256+
257+ override Function getFunction ( ) { none ( ) }
258+
259+ override Declaration getEnclosingCallable ( ) {
260+ // When flow crosses from one _enclosing callable_ to another, the
261+ // interprocedural data-flow library discards call contexts and inserts a
262+ // node in the big-step relation used for human-readable path explanations.
263+ // Therefore we want a distinct enclosing callable for each `VariableNode`,
264+ // and that can be the `Variable` itself.
265+ result = v
266+ }
267+
268+ override Type getType ( ) { result = v .getType ( ) }
269+
270+ override Location getLocation ( ) { result = v .getLocation ( ) }
271+
272+ override string toString ( ) { result = v .toString ( ) }
273+ }
274+
239275/**
240276 * Gets the node corresponding to `instr`.
241277 */
@@ -260,6 +296,9 @@ ExprNode convertedExprNode(Expr e) { result.getExpr() = e }
260296 */
261297ParameterNode parameterNode ( Parameter p ) { result .getParameter ( ) = p }
262298
299+ /** Gets the `VariableNode` corresponding to the variable `v`. */
300+ VariableNode variableNode ( Variable v ) { result .getVariable ( ) = v }
301+
263302/**
264303 * Gets the `Node` corresponding to the value of an uninitialized local
265304 * variable `v`.
0 commit comments