Skip to content

Commit 37570c7

Browse files
authored
Merge pull request #2676 from jbj/dataflow-partial-chi
C++: data flow through partial chi operands where type is known
2 parents f673791 + 52d2beb commit 37570c7

File tree

5 files changed

+31
-12
lines changed

5 files changed

+31
-12
lines changed

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,9 @@ private predicate instructionTaintStep(Instruction i1, Instruction i2) {
149149
or
150150
i2.(UnaryInstruction).getUnary() = i1
151151
or
152+
i2.(ChiInstruction).getPartial() = i1 and
153+
not isChiForAllAliasedMemory(i2)
154+
or
152155
exists(BinaryInstruction bin |
153156
bin = i2 and
154157
predictableInstruction(i2.getAnOperand().getDef()) and
@@ -209,6 +212,19 @@ private predicate modelTaintToParameter(Function f, int parameterIn, int paramet
209212
)
210213
}
211214

215+
/**
216+
* Holds if `chi` is on the chain of chi-instructions for all aliased memory.
217+
* Taint shoud not pass through these instructions since they tend to mix up
218+
* unrelated objects.
219+
*/
220+
private predicate isChiForAllAliasedMemory(Instruction instr) {
221+
instr.(ChiInstruction).getTotal() instanceof AliasedDefinitionInstruction
222+
or
223+
isChiForAllAliasedMemory(instr.(ChiInstruction).getTotal())
224+
or
225+
isChiForAllAliasedMemory(instr.(PhiInstruction).getAnInput())
226+
}
227+
212228
private predicate modelTaintToReturnValue(Function f, int parameterIn) {
213229
// Taint flow from parameter to return value
214230
exists(FunctionInput modelIn, FunctionOutput modelOut |

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

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -264,12 +264,17 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
264264
}
265265

266266
private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction iTo) {
267-
iTo.(CopyInstruction).getSourceValue() = iFrom or
268-
iTo.(PhiInstruction).getAnOperand().getDef() = iFrom or
267+
iTo.(CopyInstruction).getSourceValue() = iFrom
268+
or
269+
iTo.(PhiInstruction).getAnOperand().getDef() = iFrom
270+
or
269271
// Treat all conversions as flow, even conversions between different numeric types.
270-
iTo.(ConvertInstruction).getUnary() = iFrom or
271-
iTo.(CheckedConvertOrNullInstruction).getUnary() = iFrom or
272-
iTo.(InheritanceConversionInstruction).getUnary() = iFrom or
272+
iTo.(ConvertInstruction).getUnary() = iFrom
273+
or
274+
iTo.(CheckedConvertOrNullInstruction).getUnary() = iFrom
275+
or
276+
iTo.(InheritanceConversionInstruction).getUnary() = iFrom
277+
or
273278
// A chi instruction represents a point where a new value (the _partial_
274279
// operand) may overwrite an old value (the _total_ operand), but the alias
275280
// analysis couldn't determine that it surely will overwrite every bit of it or
@@ -279,10 +284,8 @@ private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction
279284
// due to shortcomings of the alias analysis. We may get false flow in cases
280285
// where the data is indeed overwritten.
281286
//
282-
// Allowing flow through the partial operand would be more noisy, especially
283-
// for variables that have escaped: for soundness, the IR has to assume that
284-
// every write to an unknown address can affect every escaped variable, and
285-
// this assumption shows up as data flowing through partial chi operands.
287+
// Flow through the partial operand belongs in the taint-tracking libraries
288+
// for now.
286289
iTo.getAnOperand().(ChiTotalOperand).getDef() = iFrom
287290
}
288291

cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/defaulttainttracking.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ int main(int argc, char *argv[]) {
2121
char buf[100] = "VAR = ";
2222
sink(strcat(buf, getenv("VAR")));
2323

24-
sink(buf); // BUG: no taint
25-
sink(untainted_buf); // the two buffers would be conflated if we added flow through partial chi inputs
24+
sink(buf);
25+
sink(untainted_buf); // the two buffers would be conflated if we added flow through all partial chi inputs
2626

2727
return 0;
2828
}

cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/tainted.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
| defaulttainttracking.cpp:22:20:22:25 | call to getenv | defaulttainttracking.cpp:22:8:22:33 | (const char *)... |
2222
| defaulttainttracking.cpp:22:20:22:25 | call to getenv | defaulttainttracking.cpp:22:20:22:25 | call to getenv |
2323
| defaulttainttracking.cpp:22:20:22:25 | call to getenv | defaulttainttracking.cpp:22:20:22:32 | (const char *)... |
24+
| defaulttainttracking.cpp:22:20:22:25 | call to getenv | defaulttainttracking.cpp:24:8:24:10 | buf |
2425
| defaulttainttracking.cpp:22:20:22:25 | call to getenv | test_diff.cpp:1:11:1:20 | p#0 |
2526
| defaulttainttracking.cpp:38:25:38:30 | call to getenv | defaulttainttracking.cpp:32:11:32:26 | p#0 |
2627
| defaulttainttracking.cpp:38:25:38:30 | call to getenv | defaulttainttracking.cpp:38:11:38:21 | env_pointer |

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
| defaulttainttracking.cpp:22:20:22:25 | call to getenv | defaulttainttracking.cpp:3:21:3:22 | s1 | AST only |
66
| defaulttainttracking.cpp:22:20:22:25 | call to getenv | defaulttainttracking.cpp:21:8:21:10 | buf | AST only |
77
| defaulttainttracking.cpp:22:20:22:25 | call to getenv | defaulttainttracking.cpp:22:15:22:17 | buf | AST only |
8-
| defaulttainttracking.cpp:22:20:22:25 | call to getenv | defaulttainttracking.cpp:24:8:24:10 | buf | AST only |
98
| defaulttainttracking.cpp:38:25:38:30 | call to getenv | defaulttainttracking.cpp:31:40:31:53 | dotted_address | AST only |
109
| defaulttainttracking.cpp:38:25:38:30 | call to getenv | defaulttainttracking.cpp:39:36:39:61 | (const char *)... | AST only |
1110
| defaulttainttracking.cpp:38:25:38:30 | call to getenv | defaulttainttracking.cpp:39:51:39:61 | env_pointer | AST only |

0 commit comments

Comments
 (0)