Skip to content

Commit 2806a52

Browse files
author
Robert Marsh
authored
Merge pull request #1888 from jbj/ir-dataflow-node-ipa
C++: Hide that IR DataFlow::Node is Instruction
2 parents 4283a15 + e4c9dd7 commit 2806a52

File tree

3 files changed

+67
-23
lines changed

3 files changed

+67
-23
lines changed

cpp/ql/src/semmle/code/cpp/ir/dataflow/TaintTracking.qll

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,14 @@ module TaintTracking {
133133
// Taint can flow into using ordinary data flow.
134134
DataFlow::localFlowStep(nodeFrom, nodeTo)
135135
or
136+
localInstructionTaintStep(nodeFrom.asInstruction(), nodeTo.asInstruction())
137+
}
138+
139+
/**
140+
* Holds if taint propagates from `nodeFrom` to `nodeTo` in exactly one local
141+
* (intra-procedural) step.
142+
*/
143+
private predicate localInstructionTaintStep(Instruction nodeFrom, Instruction nodeTo) {
136144
// Taint can flow through expressions that alter the value but preserve
137145
// more than one bit of it _or_ expressions that follow data through
138146
// pointer indirections.

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

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,16 @@ private import DataFlowDispatch
88
* to the callable. Instance arguments (`this` pointer) are also included.
99
*/
1010
class ArgumentNode extends Node {
11-
ArgumentNode() { exists(CallInstruction call | this = call.getAnArgument()) }
11+
ArgumentNode() { exists(CallInstruction call | this.asInstruction() = call.getAnArgument()) }
1212

1313
/**
1414
* Holds if this argument occurs at the given position in the given call.
1515
* The instance argument is considered to have index `-1`.
1616
*/
1717
predicate argumentOf(DataFlowCall call, int pos) {
18-
this = call.getPositionalArgument(pos)
18+
this.asInstruction() = call.getPositionalArgument(pos)
1919
or
20-
this = call.getThisArgument() and pos = -1
20+
this.asInstruction() = call.getThisArgument() and pos = -1
2121
}
2222

2323
/** Gets the call in which this node is an argument. */
@@ -37,24 +37,26 @@ class ReturnKind extends TReturnKind {
3737

3838
/** A data flow node that occurs as the result of a `ReturnStmt`. */
3939
class ReturnNode extends Node {
40-
ReturnNode() { exists(ReturnValueInstruction ret | this = ret.getReturnValue()) }
40+
ReturnNode() { exists(ReturnValueInstruction ret | this.asInstruction() = ret.getReturnValue()) }
4141

4242
/** Gets the kind of this returned value. */
4343
ReturnKind getKind() { result = TNormalReturnKind() }
4444
}
4545

4646
/** A data flow node that represents the output of a call. */
47-
class OutNode extends Node, CallInstruction {
47+
class OutNode extends Node {
48+
override CallInstruction instr;
49+
4850
/** Gets the underlying call. */
49-
DataFlowCall getCall() { result = this }
51+
DataFlowCall getCall() { result = instr }
5052
}
5153

5254
/**
5355
* Gets a node that can read the value returned from `call` with return kind
5456
* `kind`.
5557
*/
5658
OutNode getAnOutNode(DataFlowCall call, ReturnKind kind) {
57-
result = call and
59+
result.getCall() = call and
5860
kind = TNormalReturnKind()
5961
}
6062

@@ -192,11 +194,13 @@ class DataFlowType = Type;
192194
class DataFlowLocation = Location;
193195

194196
/** A function call relevant for data flow. */
195-
class DataFlowCall extends CallInstruction, Node {
197+
class DataFlowCall extends CallInstruction {
196198
/**
197199
* Gets the nth argument for this call.
198200
*
199201
* The range of `n` is from `0` to `getNumberOfArguments() - 1`.
200202
*/
201-
Node getArgument(int n) { result = this.getPositionalArgument(n) }
203+
Node getArgument(int n) { result.asInstruction() = this.getPositionalArgument(n) }
204+
205+
Function getEnclosingCallable() { result = this.getEnclosingFunction() }
202206
}

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

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,36 @@ private import cpp
66
private import semmle.code.cpp.ir.IR
77
private import semmle.code.cpp.controlflow.IRGuards
88

9+
/**
10+
* A newtype wrapper to prevent accidental casts between `Node` and
11+
* `Instruction`. This ensures we can add `Node`s that are not `Instruction`s
12+
* in the future.
13+
*/
14+
private newtype TIRDataFlowNode = MkIRDataFlowNode(Instruction i)
15+
916
/**
1017
* A node in a data flow graph.
1118
*
1219
* A node can be either an expression, a parameter, or an uninitialized local
1320
* variable. Such nodes are created with `DataFlow::exprNode`,
1421
* `DataFlow::parameterNode`, and `DataFlow::uninitializedNode` respectively.
1522
*/
16-
class Node extends Instruction {
23+
class Node extends TIRDataFlowNode {
24+
Instruction instr;
25+
26+
Node() { this = MkIRDataFlowNode(instr) }
27+
1728
/**
1829
* INTERNAL: Do not use. Alternative name for `getFunction`.
1930
*/
20-
Function getEnclosingCallable() { result = this.getEnclosingFunction() }
31+
Function getEnclosingCallable() { result = this.getFunction() }
32+
33+
Function getFunction() { result = instr.getEnclosingFunction() }
2134

2235
/** Gets the type of this node. */
23-
Type getType() { result = this.getResultType() }
36+
Type getType() { result = instr.getResultType() }
37+
38+
Instruction asInstruction() { this = MkIRDataFlowNode(result) }
2439

2540
/**
2641
* Gets the non-conversion expression corresponding to this node, if any. If
@@ -29,30 +44,33 @@ class Node extends Instruction {
2944
* expression.
3045
*/
3146
Expr asExpr() {
32-
result.getConversion*() = this.getConvertedResultExpression() and
47+
result.getConversion*() = instr.getConvertedResultExpression() and
3348
not result instanceof Conversion
3449
}
3550

3651
/**
3752
* Gets the expression corresponding to this node, if any. The returned
3853
* expression may be a `Conversion`.
3954
*/
40-
Expr asConvertedExpr() { result = this.getConvertedResultExpression() }
55+
Expr asConvertedExpr() { result = instr.getConvertedResultExpression() }
4156

4257
/** Gets the parameter corresponding to this node, if any. */
43-
Parameter asParameter() { result = this.(InitializeParameterInstruction).getParameter() }
58+
Parameter asParameter() { result = instr.(InitializeParameterInstruction).getParameter() }
4459

4560
/**
4661
* Gets the uninitialized local variable corresponding to this node, if
4762
* any.
4863
*/
49-
LocalVariable asUninitialized() { result = this.(UninitializedInstruction).getLocalVariable() }
64+
LocalVariable asUninitialized() { result = instr.(UninitializedInstruction).getLocalVariable() }
5065

5166
/**
5267
* Gets an upper bound on the type of this node.
5368
*/
5469
Type getTypeBound() { result = getType() }
5570

71+
/** Gets the location of this element. */
72+
Location getLocation() { result = instr.getLocation() }
73+
5674
/**
5775
* Holds if this element is at the specified location.
5876
* The location spans column `startcolumn` of line `startline` to
@@ -63,8 +81,10 @@ class Node extends Instruction {
6381
predicate hasLocationInfo(
6482
string filepath, int startline, int startcolumn, int endline, int endcolumn
6583
) {
66-
getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
84+
this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
6785
}
86+
87+
string toString() { result = instr.toString() }
6888
}
6989

7090
/**
@@ -92,19 +112,27 @@ class ExprNode extends Node {
92112
* The value of a parameter at function entry, viewed as a node in a data
93113
* flow graph.
94114
*/
95-
class ParameterNode extends Node, InitializeParameterInstruction {
115+
class ParameterNode extends Node {
116+
override InitializeParameterInstruction instr;
117+
96118
/**
97119
* Holds if this node is the parameter of `c` at the specified (zero-based)
98120
* position. The implicit `this` parameter is considered to have index `-1`.
99121
*/
100-
predicate isParameterOf(Function f, int i) { f.getParameter(i) = getParameter() }
122+
predicate isParameterOf(Function f, int i) { f.getParameter(i) = instr.getParameter() }
123+
124+
Parameter getParameter() { result = instr.getParameter() }
101125
}
102126

103127
/**
104128
* The value of an uninitialized local variable, viewed as a node in a data
105129
* flow graph.
106130
*/
107-
class UninitializedNode extends Node, UninitializedInstruction { }
131+
class UninitializedNode extends Node {
132+
override UninitializedInstruction instr;
133+
134+
LocalVariable getLocalVariable() { result = instr.getLocalVariable() }
135+
}
108136

109137
/**
110138
* A node associated with an object after an operation that might have
@@ -164,10 +192,14 @@ predicate localFlowStep(Node nodeFrom, Node nodeTo) { simpleLocalFlowStep(nodeFr
164192
* data flow. It may have less flow than the `localFlowStep` predicate.
165193
*/
166194
predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
167-
nodeTo.(CopyInstruction).getSourceValue() = nodeFrom or
168-
nodeTo.(PhiInstruction).getAnOperand().getDef() = nodeFrom or
195+
simpleInstructionLocalFlowStep(nodeFrom.asInstruction(), nodeTo.asInstruction())
196+
}
197+
198+
private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction iTo) {
199+
iTo.(CopyInstruction).getSourceValue() = iFrom or
200+
iTo.(PhiInstruction).getAnOperand().getDef() = iFrom or
169201
// Treat all conversions as flow, even conversions between different numeric types.
170-
nodeTo.(ConvertInstruction).getUnary() = nodeFrom
202+
iTo.(ConvertInstruction).getUnary() = iFrom
171203
}
172204

173205
/**

0 commit comments

Comments
 (0)