Skip to content

Commit 6d081a9

Browse files
committed
C++: Add VariableNode
1 parent 73e34f1 commit 6d081a9

File tree

2 files changed

+55
-10
lines changed

2 files changed

+55
-10
lines changed

cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,13 @@ class CastNode extends InstructionNode {
185185
CastNode() { none() } // stub implementation
186186
}
187187

188-
class DataFlowCallable = Function;
188+
/**
189+
* A function that may contain code or a variable that may contain itself. When
190+
* flow crosses from one _enclosing callable_ to another, the interprocedural
191+
* data-flow library discards call contexts and inserts a node in the big-step
192+
* relation used for human-readable path explanations.
193+
*/
194+
class DataFlowCallable = Declaration;
189195

190196
class DataFlowExpr = Expr;
191197

cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,9 @@ private import semmle.code.cpp.controlflow.IRGuards
88
private import semmle.code.cpp.ir.ValueNumbering
99
private 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
*/
2522
class 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
*/
261297
ParameterNode 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

Comments
 (0)