Skip to content

Commit 5a5832b

Browse files
author
Robert Marsh
authored
Merge pull request #2569 from jbj/ir-total-chi-flow
C++: IR data flow through total chi operands
2 parents 3c4749b + 618bf2e commit 5a5832b

File tree

5 files changed

+31
-11
lines changed

5 files changed

+31
-11
lines changed

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

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,12 @@ class Node extends TIRDataFlowNode {
5959
Parameter asParameter() { result = instr.(InitializeParameterInstruction).getParameter() }
6060

6161
/**
62+
* DEPRECATED: See UninitializedNode.
63+
*
6264
* Gets the uninitialized local variable corresponding to this node, if
6365
* any.
6466
*/
65-
LocalVariable asUninitialized() { result = instr.(UninitializedInstruction).getLocalVariable() }
67+
LocalVariable asUninitialized() { none() }
6668

6769
/**
6870
* Gets an upper bound on the type of this node.
@@ -140,15 +142,19 @@ private class ThisParameterNode extends Node {
140142
}
141143

142144
/**
145+
* DEPRECATED: Data flow was never an accurate way to determine what
146+
* expressions might be uninitialized. It errs on the side of saying that
147+
* everything is uninitialized, and this is even worse in the IR because the IR
148+
* doesn't use syntactic hints to rule out variables that are definitely
149+
* initialized.
150+
*
143151
* The value of an uninitialized local variable, viewed as a node in a data
144152
* flow graph.
145153
*/
146-
class UninitializedNode extends Node {
147-
override UninitializedInstruction instr;
148-
149-
LocalVariable getLocalVariable() { result = instr.getLocalVariable() }
154+
deprecated class UninitializedNode extends Node {
155+
UninitializedNode() { none() }
150156

151-
override string toString() { result = this.getLocalVariable().toString() }
157+
LocalVariable getLocalVariable() { none() }
152158
}
153159

154160
/**
@@ -259,7 +265,21 @@ private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction
259265
iTo.(PhiInstruction).getAnOperand().getDef() = iFrom or
260266
// Treat all conversions as flow, even conversions between different numeric types.
261267
iTo.(ConvertInstruction).getUnary() = iFrom or
262-
iTo.(InheritanceConversionInstruction).getUnary() = iFrom
268+
iTo.(InheritanceConversionInstruction).getUnary() = iFrom or
269+
// A chi instruction represents a point where a new value (the _partial_
270+
// operand) may overwrite an old value (the _total_ operand), but the alias
271+
// analysis couldn't determine that it surely will overwrite every bit of it or
272+
// that it surely will overwrite no bit of it.
273+
//
274+
// By allowing flow through the total operand, we ensure that flow is not lost
275+
// due to shortcomings of the alias analysis. We may get false flow in cases
276+
// where the data is indeed overwritten.
277+
//
278+
// Allowing flow through the partial operand would be more noisy, especially
279+
// for variables that have escaped: for soundness, the IR has to assume that
280+
// every write to an unknown address can affect every escaped variable, and
281+
// this assumption shows up as data flowing through partial chi operands.
282+
iTo.getAnOperand().(ChiTotalOperand).getDef() = iFrom
263283
}
264284

265285
/**

cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@
2929
| ref.cpp:109:15:109:20 | ref.cpp:132:13:132:15 | AST only |
3030
| ref.cpp:122:23:122:28 | ref.cpp:123:13:123:15 | AST only |
3131
| ref.cpp:125:19:125:24 | ref.cpp:126:13:126:15 | AST only |
32+
| test.cpp:75:7:75:8 | test.cpp:76:8:76:9 | AST only |
33+
| test.cpp:83:7:83:8 | test.cpp:84:8:84:18 | AST only |
34+
| test.cpp:83:7:83:8 | test.cpp:86:8:86:9 | AST only |
3235
| test.cpp:89:28:89:34 | test.cpp:92:8:92:14 | IR only |
3336
| test.cpp:100:13:100:18 | test.cpp:103:10:103:12 | AST only |
3437
| test.cpp:109:9:109:14 | test.cpp:110:10:110:12 | IR only |

cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,6 @@
3131
| test.cpp:31:8:31:8 | c | test.cpp:36:13:36:18 | call to source |
3232
| test.cpp:58:10:58:10 | t | test.cpp:50:14:50:19 | call to source |
3333
| test.cpp:71:8:71:9 | x4 | test.cpp:66:30:66:36 | source1 |
34-
| test.cpp:76:8:76:9 | u1 | test.cpp:75:7:75:8 | u1 |
35-
| test.cpp:84:8:84:18 | ... ? ... : ... | test.cpp:83:7:83:8 | u2 |
36-
| test.cpp:86:8:86:9 | i1 | test.cpp:83:7:83:8 | u2 |
3734
| test.cpp:90:8:90:14 | source1 | test.cpp:89:28:89:34 | source1 |
3835
| test.cpp:92:8:92:14 | source1 | test.cpp:89:28:89:34 | source1 |
3936
| test.cpp:110:10:110:12 | (reference dereference) | test.cpp:109:9:109:14 | call to source |

cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,5 @@
2222
| taint.cpp:250:8:250:8 | taint.cpp:223:10:223:15 | AST only |
2323
| taint.cpp:256:8:256:8 | taint.cpp:223:10:223:15 | AST only |
2424
| taint.cpp:261:7:261:7 | taint.cpp:258:7:258:12 | AST only |
25-
| taint.cpp:350:7:350:7 | taint.cpp:330:6:330:11 | AST only |
2625
| taint.cpp:351:7:351:7 | taint.cpp:330:6:330:11 | AST only |
2726
| taint.cpp:352:7:352:7 | taint.cpp:330:6:330:11 | AST only |

cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@
1414
| taint.cpp:290:7:290:7 | x | taint.cpp:275:6:275:11 | call to source |
1515
| taint.cpp:291:7:291:7 | y | taint.cpp:275:6:275:11 | call to source |
1616
| taint.cpp:337:7:337:7 | t | taint.cpp:330:6:330:11 | call to source |
17+
| taint.cpp:350:7:350:7 | t | taint.cpp:330:6:330:11 | call to source |

0 commit comments

Comments
 (0)